18 changed files with 724 additions and 80 deletions
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 895 B After Width: | Height: | Size: 895 B |
@ -0,0 +1,250 @@
|
||||
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 |
||||
}); |
||||
handler.dispatch('mousemove', { |
||||
zrX: touch.x, |
||||
zrY: touch.y |
||||
}); |
||||
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 |
||||
}); |
||||
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 |
||||
}); |
||||
handler.dispatch('click', { |
||||
zrX: touch.x, |
||||
zrY: touch.y |
||||
}); |
||||
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; |
||||
} |
@ -0,0 +1,4 @@
|
||||
{ |
||||
"component": true, |
||||
"usingComponents": {} |
||||
} |
@ -0,0 +1,4 @@
|
||||
<!-- 新的:接口对其了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> |
@ -0,0 +1,4 @@
|
||||
.ec-canvas { |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,121 @@
|
||||
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; |
||||
} |
||||
|
||||
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) { |
||||
var styles = ['fillStyle', 'strokeStyle', 'globalAlpha', |
||||
'textAlign', 'textBaseAlign', 'shadow', 'lineWidth', |
||||
'lineCap', 'lineJoin', 'lineDash', 'miterLimit', 'fontSize']; |
||||
|
||||
styles.forEach(style => { |
||||
Object.defineProperty(ctx, style, { |
||||
set: value => { |
||||
if (style !== 'fillStyle' && style !== 'strokeStyle' |
||||
|| value !== 'none' && value !== null |
||||
) { |
||||
ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value); |
||||
} |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
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 |
||||
}); |
||||
}; |
||||
}); |
||||
} |
||||
|
||||
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 |
||||
} |
||||
} |
@ -1,5 +1,5 @@
|
||||
{ |
||||
"usingComponents": { |
||||
"mp-navigation-bar": "weui-miniprogram/navigation-bar/navigation-bar" |
||||
"ec-canvas": "../../components/ec-canvas/ec-canvas" |
||||
} |
||||
} |
@ -1 +1,59 @@
|
||||
|
||||
<view class="pages"> |
||||
<mp-navigation-bar ext-class="set-bar" title="测算" back="{{false}}"></mp-navigation-bar> |
||||
<view class="main"> |
||||
<view class="top"> |
||||
<view class="top-box center"> |
||||
<image class="top-icon" src="../../assets/images/history.png"></image> |
||||
<text>历史记录</text> |
||||
</view> |
||||
</view> |
||||
<view class="content"> |
||||
<view class="info"> |
||||
<view class="tab"> |
||||
<view class="tab-item"> |
||||
<view class="tab-surf"> |
||||
<image class="my-pos" src="../../assets/images/bg2.png"></image> |
||||
<text class="tab-num">128</text> |
||||
</view> |
||||
<text class="tab-title">测算宗数</text> |
||||
</view> |
||||
<view class="tab-item"> |
||||
<view class="tab-surf"> |
||||
<image class="my-pos" src="../../assets/images/bg3.png"></image> |
||||
<text class="tab-num">39%</text> |
||||
</view> |
||||
<text class="tab-title">准确率</text> |
||||
</view> |
||||
<view class="tab-item"> |
||||
<view class="tab-surf"> |
||||
<image class="my-pos" src="../../assets/images/bg1.png"></image> |
||||
<text class="tab-num">2.43%</text> |
||||
</view> |
||||
<text class="tab-title">预测误差</text> |
||||
</view> |
||||
</view> |
||||
<view class="msg"> |
||||
<view class="msg-item"> |
||||
<view class="msg-icon"> |
||||
<image src="../../assets/images/msg.png"></image> |
||||
</view> |
||||
<text class="msg-title">测算宗数=完成测算并提交的土地宗数,单宗土地不重复;</text> |
||||
</view> |
||||
<view class="msg-item"> |
||||
<view class="msg-icon"> |
||||
</view> |
||||
<text class="msg-title">预测准确=预测溢价率差异在1%的土地宗数/测算宗数;</text> |
||||
</view> |
||||
<view class="msg-item"> |
||||
<view class="msg-icon"> |
||||
</view> |
||||
<text class="msg-title">预测误差=预测溢价率差异的绝对值的平均数;</text> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
<view class="map"> |
||||
<ec-canvas id="mychart-dom-line" canvas-id="mychart-line" ec="{{ ec }}"></ec-canvas> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</view> |
@ -1 +1,115 @@
|
||||
/* pages/calculation/calculation.wxss */ |
||||
/* pages/calculation/calculation.wxss */ |
||||
.main { |
||||
display: flex; |
||||
flex-direction: column; |
||||
padding-bottom: 0; |
||||
} |
||||
|
||||
.top { |
||||
height: 90rpx; |
||||
display: flex; |
||||
justify-content: flex-end; |
||||
align-items: center; |
||||
padding-right: 30rpx; |
||||
} |
||||
|
||||
.top-box { |
||||
font-size: 32rpx; |
||||
color: #222222; |
||||
} |
||||
|
||||
.top-box text { |
||||
text-indent: 8rpx; |
||||
} |
||||
|
||||
.top-icon { |
||||
width: 28rpx; |
||||
height: 30rpx; |
||||
} |
||||
|
||||
.content { |
||||
flex: 1; |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.info { |
||||
background-color: #ffffff; |
||||
box-sizing: border-box; |
||||
padding: 30rpx; |
||||
} |
||||
|
||||
.tab { |
||||
height: 230rpx; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
} |
||||
|
||||
.tab-item { |
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
} |
||||
|
||||
.tab-surf { |
||||
width: 180rpx; |
||||
height: 180rpx; |
||||
border-radius: 50%; |
||||
position: relative; |
||||
} |
||||
|
||||
.tab-num { |
||||
position: absolute; |
||||
left: 0; |
||||
top: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
line-height: 180rpx; |
||||
text-align: center; |
||||
z-index: 2; |
||||
font-size: 36rpx; |
||||
font-weight: bold; |
||||
color: #FFFFFF; |
||||
} |
||||
|
||||
.tab-title { |
||||
font-size: 34rpx; |
||||
font-weight: bold; |
||||
color: #262936; |
||||
} |
||||
|
||||
.msg{ |
||||
padding: 20rpx; |
||||
border: 2rpx solid #E3E3E3; |
||||
margin-top: 52rpx; |
||||
} |
||||
|
||||
.msg-item{ |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
|
||||
.msg-icon{ |
||||
width: 20rpx; |
||||
height: 24rpx; |
||||
margin-right: 16rpx; |
||||
} |
||||
|
||||
.msg-icon image{ |
||||
display: block; |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
.msg-title{ |
||||
font-size: 22rpx; |
||||
color: #838B99; |
||||
line-height: 50rpx; |
||||
} |
||||
|
||||
.map{ |
||||
margin-top: 24rpx; |
||||
background-color: #FFFFFF; |
||||
padding: 40rpx 0; |
||||
flex: 1; |
||||
} |
Loading…
Reference in new issue