提交 004f4f60 编写于 作者: yma16's avatar yma16

feat:可视化部分

上级 9b778f1f
# 云开发 quickstart
这是云开发的快速启动指引,其中演示了如何上手使用云开发的三大基础能力:
- 数据库:一个既可在小程序前端操作,也能在云函数中读写的 JSON 文档型数据库
- 文件存储:在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理
- 云函数:在云端运行的代码,微信私有协议天然鉴权,开发者只需编写业务逻辑代码
## 参考文档
- [云开发文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html)
### 云开发小程序
# 接入markdown
\ No newline at end of file
// app.js
App({
homePageArticleId:32,
lifePageArricleId:35,
globalData: {
userInfo: '',
hasUserInfo:false,
geoJson:{},
hotData:[],
/**
* @type object[{name:'',adcode:''}]
*/
geoAdcodeMap:[],
targetItem:{}
},
remoteConfig:{
baseUrl:'https://yongma16.xyz'
},
// 引入`towxml3.0`解析方法
towxml:require('/towxml/index'),
getUserProfile: function (e) {
// 推荐使用 wx.getUserProfile 获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
// 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
......@@ -33,8 +51,7 @@ App({
success: (res) => {
console.info('用户授权', res)
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
globalData:{userInfo: res.userInfo,hasUserInfo: true},
})
}
})
......@@ -72,25 +89,6 @@ App({
console.log('onLaunch', options)
},
//
// 引入`towxml3.0`解析方法
towxml:require('/towxml/index'),
//声明一个数据请求方法
getText: (url, callback) => {
wx.request({
url: url,
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success: (res) => {
if (typeof callback === 'function') {
callback(res);
};
}
});
},
onShow(options) {
// Do something when show.
console.info('show', options)
......
......@@ -15,6 +15,5 @@
"navigationBarTextStyle": "white"
},
"sitemapLocation": "sitemap.json",
"style": "v2",
"lazyCodeLoading": "requiredComponents"
"style": "v2"
}
\ No newline at end of file
......@@ -25,4 +25,5 @@ page {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
\ No newline at end of file
}
// components/base/blockInfo/blockInfo.js
const app=getApp();
Component({
/**
* 组件的属性列表
*/
properties: {
},
lifetimes:{
attached(){
this.getInfo()
}
},
/**
* 组件的初始数据
*/
data: {
areaName:'',
totalTitle:'累计数据',
todayTitle:'今日数据',
outBreakObj:{
total:[],
today:[]
}
},
/**
* 组件的方法列表
*/
methods: {
getInfo(){
const targetItem = {...app.globalData.hotData.targetItem}
const total=[
{name:'累计确诊',
value:targetItem.total.confirm,
background:'#EE5A24',
},
{name:'累计治愈',
value:targetItem.total.heal,
background:'#009432',
},
{name:`${targetItem.name}本土确诊`,
value:targetItem.total.provinceLocalConfirm,
background:'#F79F1F',
},
{name:'高风险区',
value:targetItem.total.highRiskAreaNum,
background:'#EE5A24',},
{name:'中风险区',
value:targetItem.total.mediumRiskAreaNum,
background:'#F79F1F',},
]
const today=[
{name:'新增确诊',
value:targetItem.today.confirm,
background:'#F79F1F'
},
{name:'无症状感染者',
value:targetItem.today.wzz_add,
background:'#ee5a24'
},
]
this.setData({
areaName:targetItem.name,
outBreakObj:{
total:total,
today:today
}
})
console.log('targetItem',targetItem)
console.log('data',this.data)
}
}
})
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<view class="container-block">
<view class="block-uni-title">{{areaName}}</view>
<view class="block-title">{{todayTitle}}</view>
<view class="total-container">
<block wx:for="{{outBreakObj.today}}" wx:key="*this">
<view class="block" style="background:{{item.background}}">
<view class="title">{{item.name}}</view>
<view class="content">{{item.value}}</view>
</view>
</block>
</view>
<view class="block-title">{{totalTitle}}</view>
<view class="total-container">
<block wx:for="{{outBreakObj.total}}" wx:key="*this">
<view class="block" style="background:{{item.background}}">
<view class="title">{{item.name}}</view>
<view class="content">{{item.value}}</view>
</view>
</block>
</view>
</view>>
/* components/base/blockInfo/blockInfo.wxss */
.container-block{
width: 100vw;
margin-top: 30px;
background: rgba(255,255,255,0.8);
padding: 10px;
text-align: center;
}
.total-container{
display: flex;
width: 100vw;
font-weight: bold;
}
.block{
flex: 1;
display: block;
text-align: center;
color:#ffffff;
margin:2px;
font-weight: bold;
padding:10px;
}
.block-title{
font-weight: bold;
background: cornflowerblue;
}
.block-uni-title{
font-weight: bold;
background: cornflowerblue;
font-size: 28px;
margin-bottom: 10px;
}
\ No newline at end of file
// miniprogram/components/cloudTipModal/index.js
const { isMac } = require('../../envList.js');
Component({
/**
* 页面的初始数据
*/
data: {
showUploadTip: false,
tipText: isMac ? 'sh ./uploadCloudFunction.sh' : './uploadCloudFunction.bat'
},
properties: {
showUploadTipProps: Boolean
},
observers: {
showUploadTipProps: function(showUploadTipProps) {
this.setData({
showUploadTip: showUploadTipProps
});
}
},
methods: {
onChangeShowUploadTip() {
this.setData({
showUploadTip: !this.data.showUploadTip
});
},
copyShell() {
wx.setClipboardData({
data: this.data.tipText,
});
},
}
});
{
"usingComponents": {},
"component": true
}
\ No newline at end of file
<!--miniprogram/components/cloudTipModal/index.wxml-->
<view class="install_tip" wx:if="{{showUploadTip}}">
<view class="install_tip_back"></view>
<view class="install_tip_detail">
<view class="install_tip_detail_title">体验前需部署云资源</view>
<view class="install_tip_detail_tip">请开启调试器进入终端窗口,复制并运行以下命令</view>
<view class="install_tip_detail_shell">
{{tipText}}
<view bindtap="copyShell" class="install_tip_detail_copy">复制</view>
</view>
<view bindtap="onChangeShowUploadTip" class="install_tip_detail_button">已执行命令</view>
</view>
</view>
.install_tip_back {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0,0,0,0.4);
z-index: 1;
}
.install_tip_detail {
position: fixed;
background-color: white;
right: 0;
bottom: 0;
left: 0;
top: 60%;
border-radius: 40rpx 40rpx 0 0;
padding: 50rpx;
z-index: 9;
}
.install_tip_detail_title {
font-weight: 400;
font-size: 40rpx;
text-align: center;
}
.install_tip_detail_tip {
font-size: 25rpx;
color: rgba(0,0,0,0.4);
margin-top: 20rpx;
text-align: center;
}
.install_tip_detail_shell {
margin: 70rpx 0;
display: flex;
justify-content: center;
}
.install_tip_detail_copy {
color: #546488;
margin-left: 10rpx;
}
.install_tip_detail_button {
color: #07C160;
font-weight: 500;
background-color: rgba(0,0,0,0.1);
width: 60%;
text-align: center;
height: 90rpx;
line-height: 90rpx;
border-radius: 10rpx;
margin: 0 auto;
}
\ No newline at end of file
// components/visualComponent/geoMap/geoMap.js
import * as echarts from '../../../ec-canvas/ec-canvas/echarts';
const app = getApp();
function getGeoJson() {
return new Promise((resolve, reject) => {
if(app.globalData.geoJson){
resolve(app.globalData.geoJson)
}
else{
reject({})
}
})
}
function getOutBreakData() {
return new Promise((resolve, reject) => {
if(app.globalData.hotData){
resolve(app.globalData.hotData)
}
else{
reject({})
}
})
}
async function initChart(canvas, width, height, dpr) {
const geoJson = await getGeoJson()
const outBreakData = await getOutBreakData()
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr // new
});
canvas.setChart(chart);
const geoAdcodeMap = [...app.globalData.geoAdcodeMap]
echarts.registerMap('guiZhou', geoJson);
const targetItem = {...app.globalData.hotData.targetItem};
/**
* @type object data热力值 max最大值
*/
const hotObj = {
max: 0,
data: []
}
targetItem.children.forEach(item => {
const area = geoAdcodeMap.find(mapItem => {
return mapItem.adcode.toString() === item.adcode.toString()
})
if (area) {
const count = item.total.confirm
hotObj.data.push({
name: area.name,
value: count,
adcode: area.adcode.toString
})
if (count > hotObj.max) {
hotObj.max = count
}
}
})
const option = {
title: {
text: '热力图',
subtext: '累计确诊'
},
tooltip: {
trigger: 'item',
formatter: ((item) => {
const name = item.name;
const num = (hotData.find((i) => i.name == item.name) || { value: 0 }).value;
const renderText = `<div style="text-align: left">所属地区:${name}<br>确诊病例:${num}</div>`;
return renderText
})
},
visualMap: {
min: 0,
max: hotObj.max,
left: 'left',
top: 'bottom',
text: ['', ''], // 文本,默认为数值文本
calculable: true,
color: ['#dd1818', '#ffffff']
},
toolbox: {
show: true,
orient: 'vertical',
left: 'right',
top: 'center',
feature: {
// dataView: { readOnly: false },
// restore: {},
// saveAsImage: {}
}
},
series: [{
type: 'map',
mapType: 'guiZhou',
label: {
show: true,
formatter: (item) => {
const label = item.name.toString().includes('黔南') ? item.name.toString().substring(0, 2) : item.name.toString().substring(0, 3)
return label + '\n' + item.value
}
},
itemStyle: {
normal: {
borderColor: '#389BB7',
areaColor: '#fff',
},
emphasis: {
areaColor: '#389BB7',
borderWidth: 0
}
},
animation: false,
data: hotObj.data,
}],
};
chart.setOption(option);
return chart;
}
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
geoJson: null,
mapChart: {
onInit: initChart
}
},
lifetimes: {
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
attached: function () {
// this.getGeoJson()
},
moved: function () { },
detached: function () {
},
},
/**
* 组件的方法列表
*/
methods: {
}
})
{
"component": true,
"usingComponents": {
"ec-canvas":"/ec-canvas/ec-canvas/ec-canvas"
}
}
\ No newline at end of file
<!--components/visualComponent/geoMap/geoMap.wxml-->
<view class="container-map">
<ec-canvas id="mychart-dom-area" canvas-id="mychart-area" ec="{{ mapChart }}" type="2d"></ec-canvas>
</view>
/* components/visualComponent/geoMap/geoMap.wxss */
.container-map{
position: relative;
margin-top: 50px;
width:100vw;
height:300px;
background: rgba(255,255,255,0.8);
}
// components/visualComponent/lineChart/lineChart.js
import * as echarts from '../../../ec-canvas/ec-canvas/echarts';
const app=getApp();
function initChart(canvas, width, height, dpr) {
const geoAdcodeMap = [...app.globalData.geoAdcodeMap]
const targetItem = {...app.globalData.hotData.targetItem};
/**
* @type object data热力值 max最大值
*/
const hotObj = {
data: []
}
targetItem.children.forEach(item => {
const area = geoAdcodeMap.find(mapItem => {
return mapItem.adcode.toString() === item.adcode.toString()
})
if (area) {
const totalCount = item.total.confirm
const todayCount = item.today.confirm
hotObj.data.push({
name: area.name,
totalConfirm: totalCount,
todayConfirm: todayCount,
adcode: area.adcode.toString
})
}
})
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr
});
canvas.setChart(chart);
const lineObj={
labelArray:[],
totalData:[],
todayData:[]
}
hotObj.data.forEach(item=>{
lineObj.labelArray.push(item.name)
lineObj.totalData.push(item.totalConfirm)
lineObj.todayData.push(item.todayConfirm)
})
const option = {
color: ['#EE5A24', '#F79F1F'],
title: {
text: '柱状图',
subtext: '累计确诊和新增确诊'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['累计确诊', '新增确诊'],
},
toolbox: {
orient: 'vertical',
left: 'right',
top: 'center',
show: true,
feature: {
// dataView: { show: true, readOnly: false },
magicType: { show: true, type: ['line', 'bar'] },
// restore: { show: true },
// saveAsImage: { show: true }
}
},
calculable: true,
xAxis: [
{
type: 'category',
// prettier-ignore
data: lineObj.labelArray
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: '累计确诊',
type: 'bar',
data: lineObj.totalData,
label: {
show: true,
}
},
{
name: '新增确诊',
type: 'bar',
data: lineObj.todayData,
label: {
show: true,
}
},
]
};
chart.setOption(option);
return chart;
}
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
title: '折线图',
lineChart: {
onInit: initChart
}
},
lifetimes: {
created() {
console.log('created')
},
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
attached: function () {
console.log('attached')
},
moved: function () { },
detached: function () {
},
},
/**
* 组件的方法列表
*/
methods: {
}
})
{
"component": true,
"usingComponents": {
"ec-canvas":"/ec-canvas/ec-canvas/ec-canvas"
}
}
\ No newline at end of file
<!--components/visualComponent/lineChart/lineChart.wxml-->
<view class="container-box">
<ec-canvas id="mychart-dom-line" canvas-id="mychart-line" ec="{{ lineChart }}" type="2d"></ec-canvas>
</view>
/* components/visualComponent/lineChart/lineChart.wxss */
.container-box{
position: relative;
margin-top: 30px;
width: 100vw;
height: 350px;
background: rgba(255,255,255,0.8);
}
\ No newline at end of file
import WxCanvas from './wx-canvas';
import * as echarts from './echarts';
let ctx;
function compareVersion(v1, v2) {
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
}
Component({
properties: {
canvasId: {
type: String,
value: 'ec-canvas'
},
ec: {
type: Object
},
forceUseOldCanvas: {
type: Boolean,
value: false
}
},
data: {
isUseNewCanvas: false
},
ready: function () {
// Disable prograssive because drawImage doesn't support DOM as parameter
// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.html
echarts.registerPreprocessor(option => {
if (option && option.series) {
if (option.series.length > 0) {
option.series.forEach(series => {
series.progressive = 0;
});
}
else if (typeof option.series === 'object') {
option.series.progressive = 0;
}
}
});
if (!this.data.ec) {
console.warn('组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" '
+ 'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>');
return;
}
if (!this.data.ec.lazyLoad) {
this.init();
}
},
methods: {
init: function (callback) {
const version = wx.getSystemInfoSync().SDKVersion
const canUseNewCanvas = compareVersion(version, '2.9.0') >= 0;
const forceUseOldCanvas = this.data.forceUseOldCanvas;
const isUseNewCanvas = canUseNewCanvas && !forceUseOldCanvas;
this.setData({ isUseNewCanvas });
if (forceUseOldCanvas && canUseNewCanvas) {
console.warn('开发者强制使用旧canvas,建议关闭');
}
if (isUseNewCanvas) {
// console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');
// 2.9.0 可以使用 <canvas type="2d"></canvas>
this.initByNewWay(callback);
} else {
const isValid = compareVersion(version, '1.9.91') >= 0
if (!isValid) {
console.error('微信基础库版本过低,需大于等于 1.9.91。'
+ '参见:https://github.com/ecomfe/echarts-for-weixin'
+ '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82');
return;
} else {
console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能');
this.initByOldWay(callback);
}
}
},
initByOldWay(callback) {
// 1.9.91 <= version < 2.9.0:原来的方式初始化
ctx = wx.createCanvasContext(this.data.canvasId, this);
const canvas = new WxCanvas(ctx, this.data.canvasId, false);
echarts.setCanvasCreator(() => {
return canvas;
});
// const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
const canvasDpr = 1
var query = wx.createSelectorQuery().in(this);
query.select('.ec-canvas').boundingClientRect(res => {
if (typeof callback === 'function') {
this.chart = callback(canvas, res.width, res.height, canvasDpr);
}
else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, res.width, res.height, canvasDpr);
}
else {
this.triggerEvent('init', {
canvas: canvas,
width: res.width,
height: res.height,
canvasDpr: canvasDpr // 增加了dpr,可方便外面echarts.init
});
}
}).exec();
},
initByNewWay(callback) {
// version >= 2.9.0:使用新的方式初始化
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({ node: true, size: true })
.exec(res => {
const canvasNode = res[0].node
this.canvasNode = canvasNode
const canvasDpr = wx.getSystemInfoSync().pixelRatio
const canvasWidth = res[0].width
const canvasHeight = res[0].height
const ctx = canvasNode.getContext('2d')
const canvas = new WxCanvas(ctx, this.data.canvasId, true, canvasNode)
echarts.setCanvasCreator(() => {
return canvas
})
if (typeof callback === 'function') {
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
} else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, canvasWidth, canvasHeight, canvasDpr)
} else {
this.triggerEvent('init', {
canvas: canvas,
width: canvasWidth,
height: canvasHeight,
dpr: canvasDpr
})
}
})
},
canvasToTempFilePath(opt) {
if (this.data.isUseNewCanvas) {
// 新版
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({ node: true, size: true })
.exec(res => {
const canvasNode = res[0].node
opt.canvas = canvasNode
wx.canvasToTempFilePath(opt)
})
} else {
// 旧的
if (!opt.canvasId) {
opt.canvasId = this.data.canvasId;
}
ctx.draw(true, () => {
wx.canvasToTempFilePath(opt, this);
});
}
},
touchStart(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousedown', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), 'start');
}
},
touchMove(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), 'change');
}
},
touchEnd(e) {
if (this.chart) {
const touch = e.changedTouches ? e.changedTouches[0] : {};
var handler = this.chart.getZr().handler;
handler.dispatch('mouseup', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.dispatch('click', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), 'end');
}
}
}
});
function wrapTouch(event) {
for (let i = 0; i < event.touches.length; ++i) {
const touch = event.touches[i];
touch.offsetX = touch.x;
touch.offsetY = touch.y;
}
return event;
}
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<!-- 新的:接口对其了H5 -->
<canvas wx:if="{{isUseNewCanvas}}" type="2d" class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
<!-- 旧的 -->
<canvas wx:else class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
.ec-canvas {
width: 100%;
height: 100%;
}
此差异已折叠。
export default class WxCanvas {
constructor(ctx, canvasId, isNew, canvasNode) {
this.ctx = ctx;
this.canvasId = canvasId;
this.chart = null;
this.isNew = isNew
if (isNew) {
this.canvasNode = canvasNode;
}
else {
this._initStyle(ctx);
}
// this._initCanvas(zrender, ctx);
this._initEvent();
}
getContext(contextType) {
if (contextType === '2d') {
return this.ctx;
}
}
// canvasToTempFilePath(opt) {
// if (!opt.canvasId) {
// opt.canvasId = this.canvasId;
// }
// return wx.canvasToTempFilePath(opt, this);
// }
setChart(chart) {
this.chart = chart;
}
addEventListener() {
// noop
}
attachEvent() {
// noop
}
detachEvent() {
// noop
}
_initCanvas(zrender, ctx) {
zrender.util.getContext = function () {
return ctx;
};
zrender.util.$override('measureText', function (text, font) {
ctx.font = font || '12px sans-serif';
return ctx.measureText(text);
});
}
_initStyle(ctx) {
ctx.createRadialGradient = () => {
return ctx.createCircularGradient(arguments);
};
}
_initEvent() {
this.event = {};
const eventNames = [{
wxName: 'touchStart',
ecName: 'mousedown'
}, {
wxName: 'touchMove',
ecName: 'mousemove'
}, {
wxName: 'touchEnd',
ecName: 'mouseup'
}, {
wxName: 'touchEnd',
ecName: 'click'
}];
eventNames.forEach(name => {
this.event[name.wxName] = e => {
const touch = e.touches[0];
this.chart.getZr().handler.dispatch(name.ecName, {
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
};
});
}
set width(w) {
if (this.canvasNode) this.canvasNode.width = w
}
set height(h) {
if (this.canvasNode) this.canvasNode.height = h
}
get width() {
if (this.canvasNode)
return this.canvasNode.width
return 0
}
get height() {
if (this.canvasNode)
return this.canvasNode.height
return 0
}
}
// pages/blog/blog.js
Page({
//获取应用实例
const app = getApp();
Component({
/**
* 页面的初始数据
* 继承父级样式
*/
data: {
options: {
addGlobalClass: true,
},
/**
* 生命周期函数--监听页面加载
*组件的初始数据
*/
onLoad: function (options) {
data: {
content:'子组件的content',
homeHeaderItem:'',
isLoading: true,
article: {'key':12},
baseUrl:'https://yongma16.xyz/api/',
path:'article/index/',
articleTitle:[],
currentTitle:'',
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
observers:{
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
lifetimes: {
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
attached: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
moved: function () { },
detached: function () {
},
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
// attached: function () { }, // 此处 attached 的声明会被 lifetimes 字段中的声明覆盖
// ready: function() { },
lifetimes: {
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
attached: function () {
this.getRemoteArticle()
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
moved: function () { },
detached: function () {
},
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
methods: {
getRemoteArticle:function(){
this.setData({
isLoading:true
})
const baseUrl=this.data.baseUrl
const path=this.data.path
const headers = {'Content-Type':'application/json;charset=UTF-8'}
const that=this
wx.request({
url: baseUrl+path,
headers:headers,
method:'GET',
success: (res) => {
const data=res.data
console.log(data,'data')
const title=data&&data.title
const articleObjectId=data&&data.articleObjectId
const articleTitle=title.map((item,index)=>{
return {
title:item,
id:index
}
})
const articleStr=data&&data.article&&data.article[0]
const markdownText = app.towxml(articleStr,'markdown',{
       theme:'light', //主题 dark 黑色,light白色,不填默认light
});
that.setData({
isLoading:false,
currentTitle:articleTitle&&articleTitle[0].title,
article:markdownText,
articleTitle:articleTitle
})
// 触发父组件事件
that.triggerEvent('updateArticleMenu', articleTitle)
}
});
},
/**
* 配置加载
*/
setLoading(status){
this.setData({
isLoading:status,
article:undefined
})
},
/**
* 父组件调用更新文章
* @param {*} articleStr
* @param {*} title
*/
setArticleNode(articleStr,title){
console.log('接受',articleStr,title)
const markdownText = app.towxml(articleStr,'markdown',{
       theme:'light', //主题 dark 黑色,light白色,不填默认light
events:{ //为元素绑定的事件方法
tap:e => {
console.log('tap',e);
},
change:e => {
console.log('todo',e);
}
}
});
this.setData({
isLoading:false,
article:markdownText,
currentTitle:title
})
},
onMyButtonTap: function(){
this.setData({
// 更新属性和数据的方法与更新页面数据的方法类似
})
},
// 内部方法建议以下划线开头
_myPrivateMethod: function(){
// 这里将 data.A[0].B 设为 'myPrivateData'
// this.setData({
// 'A[0].B': 'myPrivateData'
// })
},
_propertyChange: function(newVal, oldVal) {
}
}
})
\ No newline at end of file
{
"usingComponents": {}
"usingComponents": {
"towxml":"/towxml/towxml"
}
}
\ No newline at end of file
<!--pages/blog/blog.wxml-->
<text>pages/blog/blog.wxml</text>
<view class="container-blog">
<view class="loading" wx:if="{{isLoading}}">
<view class="loader-child"/>
<view class="loader-child"/>
<view class="loader-child"/>
</view>
<view class="blog-title">
{{currentTitle}}
</view>
<towxml nodes="{{article}}" class="blog-container"/>
</view>
/* pages/blog/blog.wxss */
\ No newline at end of file
/* pages/homeContent/homeContent.wxss */
.container-blog{
position: relative;
width: 100vw;
height:100vh;
background: rgba(255,255,255,0.8); /* fallback for old browsers */
overflow: auto;
}
.loading{
position: absolute;
width: 100px;
height: 100px;
perspective: 780px;
position: relative;
top:25%;
left:50%;
transform: translate(-50%,-25%);
}
.blog-container{
margin-top:30px;
width: 100vw;
height: 100vh;
}
.blog-title{
text-align: center;
font-weight: bold;
background: rgb(114, 158, 240);
position: absolute;
margin:0;
padding:0;
width: 100%;
}
\ No newline at end of file
// pages/future/future.js
Page({
const app = getApp();
const baseUrl = app.remoteConfig.baseUrl;
Component({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
* 继承父级样式
*/
options: {
addGlobalClass: true,
},
/**
* 生命周期函数--监听页面隐藏
*组件的初始数据
*/
onHide: function () {
data: {
content: '子组件的content',
btnType:'map',
homeHeaderItem: '',
isLoading: true,
article: { 'key': 12 }
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
observers: {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
lifetimes: {
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
attached: function () {
this.initData()
},
moved: function () { },
detached: function () {
},
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
// attached: function () { }, // 此处 attached 的声明会被 lifetimes 字段中的声明覆盖
// ready: function() { },
pageLifetimes: {
// 组件所在页面的生命周期函数
show: function () {
console.log('pageLifetimes')
},
hide: function () { },
resize: function () { },
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
methods: {
clickHeadBtn(e){
console.log(e)
const {btnType}=e.currentTarget.dataset
this.setData(
{btnType:btnType}
)
},
async initData() {
await this.getGeoJson()
await this.getOutBreakData()
this.setData({
isLoading: false
})
},
getGeoJson() {
if(app.globalData.geoJson){
return new Promise(resolve=>{
resolve()
})
}
const path = '/common-api/mapApp/getGeoJson/'
const headers = { 'Content-Type': 'application/json;charset=UTF-8' }
return new Promise((resolve, reject) => {
wx.request({
url: baseUrl + path,
headers: headers,
method: 'GET',
success: (res) => {
app.globalData.geoJson = res.data.data
const geoAdcodeMap = []
app.globalData.geoJson.features.map(item => {
const { properties } = item
geoAdcodeMap.push({
name: properties.name,
adcode: properties.adcode
})
})
app.globalData.geoAdcodeMap = [...geoAdcodeMap]
resolve(res.data.data)
},
fail: error => {
reject(error)
}
});
})
},
getOutBreakData() {
if(app.globalData.hotData){
return new Promise(resolve=>{
resolve()
})
}
const path = '/common-api/mapApp/outBreak/'
const headers = { 'Content-Type': 'application/json;charset=UTF-8' }
return new Promise((resolve, reject) => {
wx.request({
url: baseUrl + path,
headers: headers,
method: 'GET',
success: (res) => {
app.globalData.hotData = res.data.data
/**
* @type {string} 贵州省 adcode
*/
const targetAdcode = "520000"
const targetItem = app.globalData.hotData.areaTree[0].children.find(item => { return item.adcode === targetAdcode })
app.globalData.hotData.targetItem={...targetItem}
resolve(res.data.data)
},
fail: error => {
reject(error)
}
});
})
},
onMyButtonTap: function () {
this.setData({
// 更新属性和数据的方法与更新页面数据的方法类似
})
},
// 内部方法建议以下划线开头
_myPrivateMethod: function () {
// 这里将 data.A[0].B 设为 'myPrivateData'
// this.setData({
// 'A[0].B': 'myPrivateData'
// })
},
_propertyChange: function (newVal, oldVal) {
}
}
})
\ No newline at end of file
{
"usingComponents": {}
"usingComponents": {
"geoMap":"/components/visualComponent/geoMap/geoMap",
"lineChart":"/components/visualComponent/lineChart/lineChart",
"blockInfo":"/components/base/blockInfo/blockInfo"
}
}
\ No newline at end of file
<!--pages/future/future.wxml-->
<text>pages/future/future.wxml</text>
<!--pages/blog/blog.wxml-->
<view class="container-future">
<view class="header-container">
<view >
<view class="flex-container">
<view class='title'>疫情</view>
<view class="header-btn" class="{{btnType==='map'? 'actived':'btn-default'}}" bindtap="clickHeadBtn" data-btn-type='map'>地图</view>
<view class="header-btn" class="{{btnType==='line'? 'actived':'btn-default'}}" bindtap="clickHeadBtn" data-btn-type='line'>折线图</view>
<view class="header-btn" class="{{btnType==='blockInfo'? 'actived':'btn-default'}}" bindtap="clickHeadBtn" data-btn-type='blockInfo'>分类信息</view>
</view>
<view>
</view>
</view>
</view>
<view class="loading" wx:if="{{isLoading}}">
<view class="loader-child"/>
<view class="loader-child"/>
<view class="loader-child"/>
</view>
<view class="content-container" wx:if="{{!isLoading}}">
<geoMap wx:if="{{btnType==='map'}}" ></geoMap>
<lineChart wx:elif="{{btnType==='line'}}" bindtap="clickBottomBtn"></lineChart>
<blockInfo wx:else="{{btnType==='blockInfo'}}" bindtap="clickBottomBtn"></blockInfo>
</view>
</view>
/* pages/future/future.wxss */
\ No newline at end of file
/* pages/homeContent/homeContent.wxss */
.container-future{
position: relative;
width: 100vw;
height:100vh;
background: linear-gradient(to right, #fff 1px, transparent 1px), linear-gradient(to bottom, #fff 1px, transparent 1px);
background-repeat: repeat;
background-size: 10px 10px;
border: 1px solid #01c4ff;
overflow: hidden;
box-sizing: border-box;
}
.loading{
position: absolute;
width: 100px;
height: 100px;
perspective: 780px;
position: relative;
top:25%;
left:50%;
transform: translate(-50%,-25%);
}
.container-box{
position: relative;
width: 100vw;
height: 100vh;
overflow: auto;
}
.header-container{
position: absolute;
height:30px;
width: 100vw;
}
.content-container{
margin-top:30px;
position: absolute;
height:100vh;
width: 100vw;
overflow: auto;
}
.flex-container{
display: flex;
justify-content: center;
align-items: center;
line-height: 30px;
}
.header-container{
width: 100vw;
}
.header-btn{
color:#262626;
margin:0;
padding:0;
}
.title{
color:#ffffff;
flex:1;
font-size: 12px;
line-height: 30px;
text-align: center;
background: rgb(252, 37, 8);
}
button{
border-radius: 0;
outline: none;
font-weight: normal;
}
.btn-default{
color:#262626;
flex:1;
width:300px;
text-align: center;
background-color: #ffffff;
}
.actived{
color: #ffffff;
flex:1;
text-align: center;
background-color: rgb(8, 183, 252);
}
\ No newline at end of file
......@@ -11,31 +11,39 @@ Page({
userInfo: '',
content: '我是父组件的content',
footContent: "bottomContent",
background: [{class:'header-swiper-one',content:'数据分析'}, {class:'header-swiper-two',content:'前端开发'}, {class:'header-swiper-three',content:'全栈开发'}],
indicatorDots: true,
headerContent:'swiper',
vertical: false,
autoplay: true,
interval: 5000,
duration: 1000,
menuIsShow:false,
bottomBtn:'front',
titleObj:[],
baseUrl:'https://yongma16.xyz/api/',
path:'article/index/',
currentArticleId:0,
currentArticleTitle:''
headBackground: [
{ class: 'header-swiper-one', content: '数据分析' ,articleId:32},
{ class: 'header-swiper-two', content: '前端开发' ,articleId:33},
{ class: 'header-swiper-three', content: '全栈开发',articleId:34 }
],
swiperConfig: {
indicatorDots: true,
headerContent: 'swiper',
vertical: false,
autoplay: false,
interval: 5000,
duration: 1000,
indicatorColor: "#2e86de",
indicatorActiveColor: "#dff9fb",
},
menuIsShow: false,
bottomBtn: 'front',
titleObj: [],
baseUrl: 'https://yongma16.xyz/api/',
path: 'article/index/',
currentArticleId: 0,
currentArticleTitle: ''
},
// 监听
watch:{
bottomBtn:function(newVal,oldVal){
console.log('监听',newVal,oldVal)
watch: {
bottomBtn: function (newVal, oldVal) {
console.log('监听', newVal, oldVal)
}
},
/**
* 获取文章
*/
clickBlogTitleBtn(e){
clickBlogTitleBtn(e) {
const {id,title}=e.currentTarget.dataset
this.setData({
currentArticleId:id,
......@@ -43,39 +51,65 @@ Page({
})
this.getRemoteArticleById(id)
},
initHomeComponent(){
const articleObjId=this.data.headBackground[0].articleId
this.updateHomeContent(articleObjId)
},
updateHomeContent(articleObjId){
this.triggerHomeContent(articleObjId)
},
/**
* 卡片变动修改内容
* @param {*} e
*/
swiperChange(e){
const index=e.detail.current
const articleObjId=this.data.headBackground[index].articleId
this.updateHomeContent(articleObjId)
},
/**
* 触发子组件跟新id
*/
triggerHomeContent(id){
const homeComponent = this.selectComponent('#home-content-id')
homeComponent.getRemoteArticle(id)
},
/**
* 获取文章
* @param {*} id
* @param {*} id
*/
getRemoteArticleById(id){
const blogComponent=this.selectComponent('#blog-id')
getRemoteArticleById() {
const paramId=this.data.currentArticleId;
const blogComponent = this.selectComponent('#blog-id')
blogComponent.setLoading(true)
const baseUrl=this.data.baseUrl
const path=this.data.path
const headers = {'Content-Type':'application/json;charset=UTF-8'}
const params={
value:id
const baseUrl = this.data.baseUrl
const path = this.data.path
const that=this
const headers = { 'Content-Type': 'application/json;charset=UTF-8' }
const params = {
value: paramId
}
wx.request({
url: baseUrl+path,
headers:headers,
data:params,
method:'POST',
url: baseUrl + path,
headers: headers,
data: params,
method: 'POST',
success: (res) => {
const data=res.data
const articleStr=data&&data.article[0]
blogComponent.setArticleNode(articleStr)
const data = res.data
const articleStr = data && data.article[0]
const title=that.data.currentArticleTitle
blogComponent.setArticleNode(articleStr,title)
}
});
},
/**
* 更新菜单
* @param {Element} e
* @param {Element} e
*/
updateArticleMenu(e){
console.log('info info',e.detail),
updateArticleMenu(e) {
this.setData({
titleObj:e.detail
titleObj: e.detail
})
},
......@@ -107,45 +141,33 @@ Page({
},
// 关闭菜单
menuClose(){
this.data.menuIsShow&&this.setData({
menuClose() {
this.data.menuIsShow && this.setData({
menuIsShow: !this.data.menuIsShow
})
},
menuSwitch(){
menuSwitch() {
this.setData({
menuIsShow: !this.data.menuIsShow
})
},
// 导航的按钮
clickBottomBtn(e){
const label=e.currentTarget.dataset.label||this.data.bottomBtn
if(label==='target'||label==='life'){
return
}
this.setData({
bottomBtn:label
})
clickBottomBtn(e) {
const label = e.currentTarget.dataset.label || this.data.bottomBtn
this.setData({
bottomBtn: label
})
},
getRemoteData(){
console.log('进入home页面' ,12431243)
let url='https://yongma16.xyz/api/'
let path='article/index/'
wx.request({
url: url+path,
method:'GET',
success: (res) => {
console.log('res2222',res)
}
});
getRemoteData() {
this.getRemoteArticleById()
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.getRemoteData()
// this.initHomeComponent();
},
/**
......@@ -196,4 +218,4 @@ Page({
onShareAppMessage: function () {
}
})
\ No newline at end of file
})
<!--pages/home/home.wxml-->
<view class="container">
<view class="container-menu-expand" wx:if="{{!menuIsShow&&bottomBtn==='blog'}}">
<view class="arrow-left" bindtap="menuSwitch"></view>
</view>
<view class="container-menu-mask" wx:if="{{menuIsShow}}"></view>
<view class="container-menu-expand" wx:if="{{!menuIsShow&&bottomBtn==='blog'}}">
<view class="arrow-left" bindtap="menuSwitch"></view>
</view>
<view class="container-menu-mask" wx:if="{{menuIsShow}}"></view>
<view class="container-menu" wx:if="{{menuIsShow}}">
<view class="arrow-right" bindtap="menuSwitch"></view>
<view class="btn-ul">
记忆碎片</view>
<block wx:for="{{titleObj}}" wx:key="*this">
<view class="blog-title {{currentArticleId===item.id? 'title-actived':''}}" bindtap="clickBlogTitleBtn" data-title="{{item.title}}" data-id="{{item.id}}">{{item.title}}</view>
</block>
</view>
<view class="arrow-right" bindtap="menuSwitch"></view>
<view class="btn-ul">
记忆碎片</view>
<view class='menu-box'>
<block wx:for="{{titleObj}}" wx:key="*this">
<view class="blog-title {{currentArticleId===item.id? 'title-actived':''}}" bindtap="clickBlogTitleBtn" data-title="{{item.title}}" data-id="{{item.id}}">{{item.title}}</view>
</block>
</view>
</view>
<view class="caontainer-header" wx:if="{{bottomBtn==='front'}}">
<view class="swiper">
<swiper indicator-dots="{{indicatorDots}}"
autoplay="{{ autoplay }}" interval="{{interval}}" duration="{{duration}}" class="swiper-design">
<block wx:for="{{background}}" wx:key="*this">
<swiper indicator-dots="{{swiperConfig.indicatorDots}}" indicator-color="{{ swiperConfig.indicatorColor}}" indicator-active-color="{{swiperConfig.indicatorActiveColor}}" autoplay="{{ swiperConfig.autoplay }}" interval="{{swiperConfig.interval}}" duration="{{swiperConfig.duration}}" class="swiper-design" bindchange="swiperChange">
<block wx:for="{{headBackground}}" wx:key="*this">
<swiper-item>
<view class="swiper-item {{item.class}}">
{{item.content}}
{{item.content}}
</view>
</swiper-item>
</block>
......@@ -28,17 +29,17 @@
</view>
<view class="container-content">
<home-content class='home-content-class' headerItem='{{content}}' wx:if="{{bottomBtn==='front'}}"></home-content>
<home-content class='home-content-class' headerItem='{{content}}' wx:if="{{bottomBtn==='front'}}" id="home-content-id"></home-content>
<blog class='home-content-class' id="blog-id" wx:if="{{bottomBtn==='blog'}}" bind:updateArticleMenu="updateArticleMenu"></blog>
<future class='home-content-class' wx:if="{{bottomBtn==='target'}}"></future>
<life class='home-content-class' wx:if="{{bottomBtn==='life'}}"></life>
</view>
<view class="container-footer">
<view class="container-footer-btn-menu">
<view class="default-btn active {{bottomBtn==='front'? 'btn-actived':''}}" bindtap="clickBottomBtn" data-label='front'>主页</view>
<view class="default-btn active {{bottomBtn==='blog'? 'btn-actived':''}}" bindtap="clickBottomBtn" data-label='blog'>博客</view>
<view class="default-btn active {{bottomBtn==='target'? 'btn-actived':''}}" bindtap="clickBottomBtn" data-label='target'>未来</view>
<view class="default-btn active {{bottomBtn==='life'? 'btn-actived':''}}" bindtap="clickBottomBtn" data-label='life'>生活</view>
<view class="default-btn active {{bottomBtn==='front'? 'btn-actived':''}}" bindtap="clickBottomBtn" data-label='front'>主页</view>
<view class="default-btn active {{bottomBtn==='blog'? 'btn-actived':''}}" bindtap="clickBottomBtn" data-label='blog'>博客</view>
<view class="default-btn active {{bottomBtn==='target'? 'btn-actived':''}}" bindtap="clickBottomBtn" data-label='target'>可视化</view>
<view class="default-btn active {{bottomBtn==='life'? 'btn-actived':''}}" bindtap="clickBottomBtn" data-label='life'>关于</view>
</view>
</view>
</view>
\ No newline at end of file
......@@ -10,7 +10,7 @@ page {
position: relative;
width: 100vw;
height:100vh;
background: #1c92d2;
background: rgba(4, 173, 240, 0.6);
}
/* 箭头 //上右边下左 */
......@@ -57,11 +57,31 @@ page {
position: absolute;
left: 0;
z-index: 1;
width:30%;
width:50%;
font-size: 12px;
height:100%;
background-color: rgba(0, 0, 0,.8);
overflow-y: auto;
}
.menu-box{
margin-bottom: 80px;
}
/* mask */
.container-menu-mask{
position: absolute;
right: 0;
z-index: 1;
width:50%;
height:100%;
background-color: rgba(0, 0, 0,.5);
overflow: hidden;
margin-bottom: 60px;
}
.container-menu-expand{
position: absolute;
left: 0;
z-index: 1;
}
.btn-ul{
position: relative;
......@@ -79,23 +99,7 @@ page {
.title-actived{
color:#1c92d2 !important;
}
/* mask */
.container-menu-mask{
position: absolute;
right: 0;
z-index: 1;
width:70%;
height:100%;
background-color: rgba(0, 0, 0,.5);
overflow: hidden;
}
.container-menu-expand{
position: absolute;
left: 0;
z-index: 1;
}
.caontainer-header{
height:150px;
......@@ -169,7 +173,7 @@ page {
height:60px;
line-height: 60px;
}
.default-btn:active{
.default-btn:active,default-btn:active:hover{
background-color:rgb(8, 183, 252);
color:#ffffff;
}
......@@ -180,6 +184,7 @@ page {
box-shadow: 0 5px 5px 5px rgba(8, 183, 252,.5);
}
/* loading */
.loader-child {
......@@ -232,4 +237,5 @@ page {
100% {
transform: rotateX(35deg) rotateY(55deg) rotateZ(360deg);
}
}
\ No newline at end of file
}
// pages/homeContent/homeContent.js
Page({
// // "lazyCodeLoading": "requiredComponents"
//获取应用实例
const app = getApp();
Component({
/**
* 继承父级样式
*/
options: {
addGlobalClass: true,
},
// prop
properties: {
headerItem:String
},
// observers: {
// headerItem: function(newVal,oldVal) {
// console.log('change',newVal,oldVal)
// this.setData({
// homeHeaderItem: newVal
// });
// }
// },
/**
* 页面的初始数据
*组件的初始数据
*/
data: {
content:'子组件的content',
homeHeaderItem:'',
isLoading: true,
article: {}
article: {'key':12},
baseUrl:'https://yongma16.xyz/api/',
path:'article/blog/',
// 35, 34, 33, 32
currentArticleId:32,
},
observers:{
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function () {
const _ts = this;
app.getText('https://www.vvadd.com/wxml_demo/demo.txt?v=2',res => {
let obj = app.towxml(res.data,'markdown',{
// theme:'dark',
events:{
tap:e => {
console.log('tap',e);
},
change:e => {
console.log('todo',e);
}
}
});
_ts.setData({
article:obj,
isLoading: false
});
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
console.log('进入homePage home-content 渲染开始 onready')
console.log('传递的header-item',this)
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
lifetimes: {
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
attached: function () {
const id=app.homePageArticleId
this.getRemoteArticle(id)
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
moved: function () {},
detached: function () {
},
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
// attached: function () { }, // 此处 attached 的声明会被 lifetimes 字段中的声明覆盖
// ready: function() { },
pageLifetimes: {
// 组件所在页面的生命周期函数
show: function () {
console.log('pageLifetimes')
},
hide: function () { },
resize: function () { },
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
methods: {
getRemoteArticle:function(id){
this.setData({
isLoading:true
})
const baseUrl=this.data.baseUrl
const path=this.data.path
const headers = {'Content-Type':'application/json;charset=UTF-8'}
const that=this
const params={
id:id
}
wx.request({
url: baseUrl+path,
headers:headers,
data:params,
method:'POST',
success: (res) => {
const data=res.data
const articleStr=data&&data.article&&data.article
const markdownText = app.towxml(articleStr,'markdown',{
       theme:'light', //主题 dark 黑色,light白色,不填默认light
       base: baseUrl+path,
events:{ //为元素绑定的事件方法
tap:e => {
console.log('tap',e);
},
change:e => {
console.log('todo',e);
}
}
});
that.setData({
isLoading:false,
article:markdownText
})
}
});
},
onMyButtonTap: function(){
this.setData({
// 更新属性和数据的方法与更新页面数据的方法类似
})
},
// 内部方法建议以下划线开头
_myPrivateMethod: function(){
// 这里将 data.A[0].B 设为 'myPrivateData'
// this.setData({
// 'A[0].B': 'myPrivateData'
// })
},
_propertyChange: function(newVal, oldVal) {
}
}
})
\ No newline at end of file
{
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"usingComponents": {
"towxml":"/towxml/towxml"
}
......
<!--pages/homeContent/homeContent.wxml-->
<!-- <text>pages/homeContent/homeContent.wxml</text> -->
<!-- <view class="container"> -->
<!-- <text>content内容</text> -->
<!-- {{headerItem}} -->
<!-- {{content + headerItem}} -->
<!-- <web-view src="https://yongma16.xyz/" /> -->
<!-- </view> -->
<!--index.wxml-->
<!--loading-->
<view class="container-front">
<view class="loading" wx:if="{{isLoading}}">
<image class="loading__icon" src="/images/loading.svg"></image>
<view class="loader-child"/>
<view class="loader-child"/>
<view class="loader-child"/>
</view>
<towxml nodes="{{article}}"/>
</view>
<!--使用towxml-->
<towxml nodes="{{article}}"/>
\ No newline at end of file
/* pages/homeContent/homeContent.wxss */
.container{
.container-front{
position: relative;
width: 100%;
height:100%;
background: #262626;
overflow: hidden;
width: 100vw;
height:100vh;
background: rgba(255,255,255,0.8); /* fallback for old browsers */
overflow: auto;
}
.loading{
position: absolute;
width: 100px;
height: 100px;
perspective: 780px;
position: relative;
top:25%;
left:50%;
transform: translate(-50%,-25%);
}
......@@ -4,12 +4,14 @@
Page({
data: {
title: "alpha测试阶段",
userImageUrl: "https://res.wx.qq.com/wxdoc/dist/assets/img/0.4cb08bb4.jpg",
loginTitle: "授权",
userName: '未授权用户',
detailInfo:'关于:前端程序员的生活博客',
title: "yma16博客",
userImageUrl: "https://yongma16.xyz/staticFile/common/img/logo.png",
loginTitle: "点击授权",
userName: '',
userInfo: {},
hasUserInfo: false
hasUserInfo: false,
isloading:true,
},
getUserInfoBtn: function (info) {fgetUserProfile
wx.showLoading({
......@@ -52,15 +54,11 @@ Page({
},
// 跳转到home
jumpTohome: function () {
console.log('跳转到home')
console.log('this.pageRouter',this.pageRouter)
wx.navigateTo({
url: '/pages/home/home'
})
},
onLoad: function (options) {
console.log('this page', this)
console.log('this.pageRouter',this.pageRouter)
this.jumpTohome()
// 页面创建时执行
},
......
{
"usingComponents": {
"cloud-tip-modal": "/components/cloudTipModal/index"
}
}
\ No newline at end of file
<!--
<view class="container">
<view class="title">快速了解云开发</view>
<view class="top_tip">免鉴权接口调用 免部署后台 高并发</view>
<view class="power" wx:key="title" wx:for="{{powerList}}" wx:for-item="power">
<view class="power_info" data-index="{{index}}" bindtap="onClickPowerInfo">
<view class="power_info_text">
<view class="power_info_text_title">{{power.title}}</view>
<view class="power_info_text_tip">{{power.tip}}</view>
</view>
<image wx:if="{{!power.showItem}}" class="power_info_more" src="../../images/arrow.svg"></image>
<image wx:if="{{power.showItem}}" class="power_info_less" src="../../images/arrow.svg"></image>
</view>
<view wx:if="{{power.showItem}}">
<view wx:key="title" wx:for="{{power.item}}">
<view class="line"></view>
<view class="power_item" bindtap="jumpPage" data-page="{{item.page}}">
<view class="power_item_title">{{item.title}}</view>
<image class="power_item_icon" src="../../images/arrow.svg"></image>
</view>
</view>
</view>
</view>
<view class="environment" bindtap="onChangeShowEnvChoose">当前环境 {{ selectedEnv.alias }}</view>
<cloud-tip-modal showUploadTipProps="{{showUploadTip}}"></cloud-tip-modal>
</view> -->
<view class="container">
<view class="title">{{title}}</view>
<view class="user-image-box">
......@@ -39,7 +6,16 @@
</view>
<view class="user-info">
</view>
<button type="primary" plain="true" bindtap="getUserProfile" class="user-login" bindgetuserinfo="getUserInfoBtn">{{loginTitle}}</button>
<cloud-tip-modal showUploadTipProps="{{showUploadTip}}"></cloud-tip-modal>
</view>
\ No newline at end of file
<view class="login-container">
<button type="primary" plain="true" bindtap="getUserProfile" class="user-login" bindgetuserinfo="getUserInfoBtn">{{loginTitle}}</button></view>
</view>
<view class="loading-container">
<view class="loading" wx:if="isloading">
<view class="loader-child"/>
<view class="loader-child"/>
<view class="loader-child"/>
</view>
</view>
<view class="detail-info">{{detailInfo}}</view>
\ No newline at end of file
......@@ -2,7 +2,7 @@
page {
padding-top: 54rpx;
background: #076585;
background: #05b3ec;
color: #fff;
/* fallback for old browsers */
background: -webkit-linear-gradient(to top, #fff, #076585);
......@@ -13,8 +13,14 @@ page {
padding-bottom: 60rpx;
}
.login-container{
margin-top:50px !important;
}
.user-login {
width: 100px !important;
width:120px !important;
color: #fff !important;
border-color: #fff !important;
}
......@@ -124,4 +130,90 @@ page {
color: rgba(0, 0, 0, 0.4);
font-size: 24rpx;
margin-top: 25%;
}
.detail-info{
position: absolute;
bottom:0;
width: 100vw;
height:40px;
text-align: center;
font-size: 12px;
font-weight: bold;
color: #076585;
}
.loading-container{
position: absolute;
height: 100px;
height:100px;
left:50%;
bottom: 60px;
transform: translate(-50%);
}
.loading{
position: absolute;
width: 100px;
height: 100px;
perspective: 780px;
position: relative;
top:25%;
left:50%;
transform: translate(-50%,-25%);
bottom: 80px;
}
/* loading */
.loader-child {
position: absolute;
width: 100px;
height: 100px;
box-sizing: border-box;
border-radius: 50%;
}
.loader-child:nth-of-type(1) {
left: 0%;
top: 0%;
animation: rotate-one 1.15s linear infinite;
border-bottom: 3px solid #ffffff;
}
.loader-child:nth-of-type(2) {
right: 0%;
top: 0%;
animation: rotate-two 1.15s linear infinite;
border-right: 3px solid #ffffff;
}
.loader-child:nth-of-type(3) {
right: 0%;
bottom: 0%;
animation: rotate-three 1.15s linear infinite;
border-top: 3px solid #ffffff;
}
@keyframes rotate-one {
0% {
transform: rotateX(35deg) rotateY(-45deg) rotateZ(0deg);
}
100% {
transform: rotateX(35deg) rotateY(-45deg) rotateZ(360deg);
}
}
@keyframes rotate-two {
0% {
transform: rotateX(50deg) rotateY(10deg) rotateZ(0deg);
}
100% {
transform: rotateX(50deg) rotateY(10deg) rotateZ(360deg);
}
}
@keyframes rotate-three {
0% {
transform: rotateX(35deg) rotateY(55deg) rotateZ(0deg);
}
100% {
transform: rotateX(35deg) rotateY(55deg) rotateZ(360deg);
}
}
\ No newline at end of file
// const requestInterval = (fn, delay) => {
// let start = new Date().getTime();
// let handle = {
// value: 0
// };
// let loop = () => {
// handle.value = requestAnimationFrame(loop);
// let current = new Date().getTime();
// let delta = current - start;
// if (delta >= delay) {
// fn();
// start = new Date().getTime();
// }
// };
// handle.value = requestAnimationFrame(loop);
// return handle;
// };
// const renderIdFont=(idName)=>{
// //random
// const sample = (arr) => arr[Math.floor(Math.random() * arr.length)];
// const bubbleSizes = [3, 6, 9, 12];
// //render
// let bubbleText = document.getElementById(idName);
// if(!bubbleText){
// return 0
// }
// let bubblePositions = Array.from(
// Array(bubbleText.offsetWidth).keys()
// );
// setTimeout(() => {
// let bubbleSize = sample(bubbleSizes);
// let bubblePosition = sample(bubblePositions);
// let bubble = document.createElement("div");
// bubble.className = "bubble";
// bubble.style.width = `${bubbleSize}px`;
// bubble.style.height = `${bubbleSize}px`;
// bubble.style.left = `${bubblePosition}px`;
// bubbleText.append(bubble);
// let bubbleAnimation = bubble.animate(
// [{
// bottom: "10px",
// opacity: 1
// }, {
// bottom: "180%",
// opacity: 0.6
// }], {
// fill: "forwards",
// duration: 3000
// }
// );
// bubbleAnimation.onfinish = () => bubble.remove();
// }, 500);
// }
// const init = () => {
// let idArray=['bubblingId1','bubblingId2','bottomWordId3']
// for(let i=0,length=idArray.length;i<length;++i){
// renderIdFont(idArray[i])
// }
// getTime()
// // 获取词语
// setTimeout(()=>{
// const baseUrl='https://yongma16.xyz/api/'
// const path='get-word/'
// // const headers = {'Content-Type':'application/json;charset=UTF-8'}
// wx.request({
// url: baseUrl+path,
// success: (res) => {
// let data=res.data
// let word=data.data
// writeWord(word)
// }
// });
// },100)
// getWord()
// }
// const getWord=()=>{
// setTimeout(()=>{
// const baseUrl='https://yongma16.xyz/api/'
// const path='get-word/'
// // const headers = {'Content-Type':'application/json;charset=UTF-8'}
// wx.request({
// url: baseUrl+path,
// success: (res) => {
// let data=res.data
// let word=data.data
// writeWord(word)
// }
// });
// return getWord()
// },8000)
// }
// // 打字机效果
// const writeWord=(word)=>{
// document.getElementById('bubblingId2').innerText=word
// }
// const getTime=()=>{
// let start=new Date('2022-02-20')
// let now=new Date()
// let diff=now.valueOf()-start.valueOf();//
// let onDay=24*60*60*1000;
// let day=Math.ceil(diff/onDay);//天数
// document.getElementById('dayCalFontId').innerText=`在一起:${day}天`
// }
\ No newline at end of file
// pages/life/life.js
Page({
const app=getApp();
Component({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
* 继承父级样式
*/
options: {
addGlobalClass: true,
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
* 页面的初始数据
*/
onHide: function () {
data: {
isLoading: true,
baseUrl: 'https://yongma16.xyz/api/',
path: 'get-word/',
articlePath:'article/blog/',
content: 'loading...',
togetherDate: (() => {
const start = new Date('2022-02-20')
const now = new Date()
const diff = now.valueOf() - start.valueOf();//
const onDay = 24 * 60 * 60 * 1000;
const day = Math.ceil(diff / onDay);//天数
const dayStr = `${day}天`
return dayStr
})(),
autoTimer: null,
article: ''
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
lifetimes: {
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
attached: function () {
this.initArticle()
// this.updateContent();
},
moved: function () { this.clearTimerFunc() },
detached: function () {
this.clearTimerFunc()
},
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
// 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
// attached: function () { }, // 此处 attached 的声明会被 lifetimes 字段中的声明覆盖
// ready: function() { },
pageLifetimes: {
// 组件所在页面的生命周期函数
show: function () {
console.log('pageLifetimes')
},
hide: function () { },
resize: function () { },
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
methods: {
initArticle() {
const articleId=app.lifePageArricleId
this.getRemoteArticle(articleId)
},
clearTimerFunc: function () {
//清除定时器
if (this.data.autoTimer) {
clearTimeout(this.data.autoTimer)
}
},
updateContent: function () {
const baseUrl = this.data.baseUrl
const path = this.data.path
const headers = { 'Content-Type': 'application/json;charset=UTF-8' }
const that = this
wx.request({
url: baseUrl + path,
headers: headers,
method: 'GET',
success: (res) => {
const data = res.data
const word = data.data
that.setData(
{
content: word
}
)
}
});
// that.setData({
// autoTimer:setTimeout(()=>{
// return that.updateContent()
// },8000)
// })
},
getRemoteArticle(id){
this.setData({
isLoading:true
})
const baseUrl=this.data.baseUrl
const path=this.data.articlePath
const headers = {'Content-Type':'application/json;charset=UTF-8'}
const that=this
const params={
id:id
}
wx.request({
url: baseUrl+path,
headers:headers,
data:params,
method:'POST',
success: (res) => {
console.log('res',res)
const data=res.data
const articleStr=data&&data.article&&data.article
const markdownText = app.towxml(articleStr,'markdown',{
       theme:'light', //主题 dark 黑色,light白色,不填默认light
       base: baseUrl+path,
events:{ //为元素绑定的事件方法
tap:e => {
console.log('tap',e);
},
change:e => {
console.log('todo',e);
}
}
});
that.setData({
isLoading:false,
article:markdownText
})
}
});
},
onMyButtonTap: function () {
this.setData({
// 更新属性和数据的方法与更新页面数据的方法类似
})
},
// 内部方法建议以下划线开头
_myPrivateMethod: function () {
// 这里将 data.A[0].B 设为 'myPrivateData'
// this.setData({
// 'A[0].B': 'myPrivateData'
// })
},
_propertyChange: function (newVal, oldVal) {
}
}
})
\ No newline at end of file
{
"usingComponents": {}
"usingComponents": {
"towxml":"/towxml/towxml"
}
}
\ No newline at end of file
<!--pages/life/life.wxml-->
<text>pages/life/life.wxml</text>
<!-- pages/life/life.wxml -->
<view class="container-life">
<view class="loading" wx:if="{{isLoading}}">
<view class="loader-child"/>
<view class="loader-child"/>
<view class="loader-child"/>
</view>
<view class='container-box'>
<towxml nodes="{{article}}" class="blog-container"/>
</view>
<!-- <view class='gril-friend'>
<view class="gril-friend-header">
<view>遇见</view>
<view>在一起:{{togetherDate}}</view>
</view>
<view class="box">
<view class='heart'></view></view>
<view class="gril-friend-content">{{content}}</view>
<view class="gril-friend-bottom">
<view class='gril-friend-content-left'>
<view >一语寄相思</view>
</view>
<view class='gril-friend-content-right'> -->
<!-- <view>
柚屿</view> -->
<!-- <view class='container-life-right-font'>
yma16</view>
</view>
</view>
</view>
<view class='beat-heart'></view> -->
</view>
/* pages/life/life.wxss */
\ No newline at end of file
/* pages/life/life.wxss */
.container-life{
position: relative;
width: 100vw;
height:100vh;
color:#ff00aa;
background: #fff; /* fallback for old browsers */
overflow: hidden;
animation-name:backdiv;
animation-duration: 6s;
animation-iteration-count: infinite;
}
.container-box{
position: relative;
width: 100vw;
height:100vh;
}
.loading{
position: absolute;
width: 100px;
height: 100px;
perspective: 780px;
position: relative;
top:25%;
left:50%;
transform: translate(-50%,-25%);
}
.gril-friend{
position: relative;
padding:20px;
height: 100%;
}
.gril-friend-header{
position: relative;
display: flex;
justify-content: space-between;
height: 25%;
}
.gril-friend-content{
position: absolute;
left: 50%;
top:50%;
transform: translate(-50%,-50%);
text-align: center;
font-size: 16px;
color: #ff00aa;
/* animation-name:heart-font;
animation-duration: 6s;
z-index:1;
animation-iteration-count: infinite; */
}
.gril-friend-bottom{
position: absolute;
display: flex;
height: 25%;
justify-content: space-between;
width: 100vw;
bottom: 0;
}
.gril-friend-left{
position: relative;
text-align: left;
}
.container-life-right{
position: relative;
padding-right:20px;
}
.container-life-right-font{
margin-right: 40px;
}
.box{
position: absolute;
left:50%;
top:50%;
transform: translate(-50%,-50%);
}
.heart{
width:200px;
height:200px;
background: pink;
transform: rotate(45deg);
/* animation-name:change;
animation-duration: 6s;
animation-iteration-count: infinite; */
}
/* 伪类创建 */
.heart::before{
content:'';
width:200px;
height:200px;
background: pink;
border-radius: 50%;
position: absolute;
/* 定位 */
transform: translateX(-100px);
}
.heart::after{
content:'';
width:200px;
height:200px;
background: pink;
border-radius: 50%;
position: absolute;
/* 定位 */
transform: translateY(-100px);
/* transform: translateX(-100px); */
}
@keyframes change{
0%{
transform: rotate(45deg) scale(0.5);
}
50%{
transform: rotate(45deg) scale(0.8);
}
100%{
transform: rotate(45deg) scale(0.5);
}
}
@keyframes backdiv {
50% {
background: #ffe6f2;
}
}
@keyframes heart-font{
0%{
left: 50%;
top:50%;
transform: translate(-50%,-50%) scale(0.5);
}
50%{
left: 50%;
top:50%;
transform: translate(-50%,-50%) scale(0.8);
}
100%{
left: 50%;
top:50%;
transform: translate(-50%,-50%) scale(0.5);
}
}
\ No newline at end of file
......@@ -41,7 +41,7 @@
},
"appid": "wx373f33f993c688d1",
"projectname": "yma16_program",
"libVersion": "2.20.1",
"libVersion": "2.27.0",
"cloudfunctionTemplateRoot": "cloudfunctionTemplate",
"condition": {
"search": {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册