Merge branch 'dev' of codeup.aliyun.com:61c14a7efa282c88e103c23f/oak-general-business into dev

This commit is contained in:
Xu Chang 2022-12-22 16:41:53 +08:00
commit 7f3daf41a5
21 changed files with 879 additions and 24 deletions

View File

@ -1,7 +1,11 @@
import React from 'react';
import { WebComponentProps } from 'oak-frontend-base'; import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../general-app-domain'; import { EntityDict } from '../../../general-app-domain';
export default function Render(props: WebComponentProps<EntityDict, 'user', false, { export default function Render(props: WebComponentProps<EntityDict, 'user', false, {
count?: number; count?: number;
onClick?: (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => void;
className?: string;
style?: React.CSSProperties;
}, { }, {
goMessageList: () => void; goMessageList: () => void;
}>): JSX.Element; }>): JSX.Element;

View File

@ -3,14 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib"); var tslib_1 = require("tslib");
var jsx_runtime_1 = require("react/jsx-runtime"); var jsx_runtime_1 = require("react/jsx-runtime");
var antd_mobile_1 = require("antd-mobile"); var antd_mobile_1 = require("antd-mobile");
var classnames_1 = tslib_1.__importDefault(require("classnames"));
var icons_1 = require("@ant-design/icons"); var icons_1 = require("@ant-design/icons");
var mobile_module_less_1 = tslib_1.__importDefault(require("./mobile.module.less")); var mobile_module_less_1 = tslib_1.__importDefault(require("./mobile.module.less"));
function Render(props) { function Render(props) {
var data = props.data, methods = props.methods; var data = props.data, methods = props.methods;
var count = data.count; var count = data.count, className = data.className, onClick = data.onClick, style = data.style;
var goMessageList = methods.goMessageList; var goMessageList = methods.goMessageList;
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(antd_mobile_1.Badge, tslib_1.__assign({ content: count || '' }, { children: (0, jsx_runtime_1.jsx)(icons_1.BellOutlined, { className: mobile_module_less_1.default.icon, onClick: function () { return ((0, jsx_runtime_1.jsx)(antd_mobile_1.Badge, tslib_1.__assign({ content: count || '' }, { children: (0, jsx_runtime_1.jsx)(icons_1.BellOutlined, { className: (0, classnames_1.default)(mobile_module_less_1.default.icon, className), style: style, onClick: function (e) {
goMessageList(); if (typeof onClick === 'function') {
} }) })) })); onClick(e);
return;
}
goMessageList();
} }) })));
} }
exports.default = Render; exports.default = Render;

View File

@ -1,7 +1,13 @@
import React from 'react';
import { WebComponentProps } from 'oak-frontend-base'; import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../general-app-domain'; import { EntityDict } from '../../../general-app-domain';
export default function Render(props: WebComponentProps<EntityDict, 'user', false, { export default function Render(props: WebComponentProps<EntityDict, 'user', false, {
count?: number; count?: number;
onClick: (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => void;
className?: string;
style?: React.CSSProperties;
buttonStyle?: React.CSSProperties;
buttonClassName?: string;
}, { }, {
goMessageList: () => void; goMessageList: () => void;
}>): JSX.Element; }>): JSX.Element;

View File

@ -4,14 +4,19 @@ var tslib_1 = require("tslib");
var jsx_runtime_1 = require("react/jsx-runtime"); var jsx_runtime_1 = require("react/jsx-runtime");
var react_1 = require("react"); var react_1 = require("react");
var antd_1 = require("antd"); var antd_1 = require("antd");
var classnames_1 = tslib_1.__importDefault(require("classnames"));
var icons_1 = require("@ant-design/icons"); var icons_1 = require("@ant-design/icons");
var drawerList_1 = tslib_1.__importDefault(require("../../../pages/message/drawerList")); var drawerList_1 = tslib_1.__importDefault(require("../../../pages/message/drawerList"));
var web_module_less_1 = tslib_1.__importDefault(require("./web.module.less")); var web_module_less_1 = tslib_1.__importDefault(require("./web.module.less"));
function Render(props) { function Render(props) {
var data = props.data; var data = props.data;
var count = data.count; var count = data.count, className = data.className, onClick = data.onClick, style = data.style, buttonStyle = data.buttonStyle, buttonClassName = data.buttonClassName;
var _a = tslib_1.__read((0, react_1.useState)(false), 2), open = _a[0], setOpen = _a[1]; var _a = tslib_1.__read((0, react_1.useState)(false), 2), open = _a[0], setOpen = _a[1];
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(antd_1.Badge, tslib_1.__assign({ count: count }, { children: (0, jsx_runtime_1.jsx)(antd_1.Button, { className: web_module_less_1.default.btn, type: "text", shape: "circle", icon: (0, jsx_runtime_1.jsx)(icons_1.BellOutlined, {}), onClick: function () { return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(antd_1.Badge, tslib_1.__assign({ count: count }, { children: (0, jsx_runtime_1.jsx)(antd_1.Button, { className: (0, classnames_1.default)(web_module_less_1.default.btn, buttonClassName), style: buttonStyle, type: "text", shape: "circle", icon: (0, jsx_runtime_1.jsx)(icons_1.BellOutlined, { className: (0, classnames_1.default)(web_module_less_1.default.icon, className), style: style }), onClick: function (e) {
if (typeof onClick === 'function') {
onClick(e);
return;
}
setOpen(true); setOpen(true);
} }) })), (0, jsx_runtime_1.jsx)(drawerList_1.default, { open: open, onClose: function () { } }) })), (0, jsx_runtime_1.jsx)(drawerList_1.default, { open: open, onClose: function () {
setOpen(false); setOpen(false);

View File

@ -0,0 +1,265 @@
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;
}

View File

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@ -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>

View File

@ -0,0 +1,4 @@
.ec-canvas {
width: 100%;
height: 100%;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,111 @@
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
}
}

View File

@ -1,6 +1,6 @@
/** index.wxss **/
.container { .container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1;
background-color: var(--oak-bg-color-page); background-color: var(--oak-bg-color-page);
} }

View File

@ -77,7 +77,8 @@
"clean": "rimraf lib/*", "clean": "rimraf lib/*",
"copy-files": "copyfiles -u 1 src/**/*.svg lib/ & copyfiles -u 1 src/**/*.xml lib/ & copyfiles -u 1 src/**/*.wxml lib/ & copyfiles -u 1 src/**/*.wxs lib/ & copyfiles -u 1 src/miniprogram_npm/**/*.js lib/ ", "copy-files": "copyfiles -u 1 src/**/*.svg lib/ & copyfiles -u 1 src/**/*.xml lib/ & copyfiles -u 1 src/**/*.wxml lib/ & copyfiles -u 1 src/**/*.wxs lib/ & copyfiles -u 1 src/miniprogram_npm/**/*.js lib/ ",
"copy-less": "copyfiles -u 1 src/**/*.less lib/", "copy-less": "copyfiles -u 1 src/**/*.less lib/",
"build": "tsc && npm run copy-files && npm run copy-less", "copy-wxss": "copyfiles -u 1 src/**/*.wxss lib/",
"build": "tsc && npm run copy-files && npm run copy-less && npm run copy-wxss",
"gen:areaDebug": "ts-node ./scripts/generateAreaDebug.ts", "gen:areaDebug": "ts-node ./scripts/generateAreaDebug.ts",
"clean:dir": "ts-node ./scripts/cleanDtsAndJs", "clean:dir": "ts-node ./scripts/cleanDtsAndJs",
"test": "ts-node ./test/test.ts", "test": "ts-node ./test/test.ts",

View File

@ -1,5 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Button, Badge } from 'antd'; import { Button, Badge } from 'antd';
import classNames from 'classnames';
import { BellOutlined } from '@ant-design/icons'; import { BellOutlined } from '@ant-design/icons';
import { WebComponentProps } from 'oak-frontend-base'; import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../general-app-domain'; import { EntityDict } from '../../../general-app-domain';
@ -14,6 +15,11 @@ export default function Render(
false, false,
{ {
count?: number; count?: number;
onClick: (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => void;
className?: string;
style?: React.CSSProperties;
buttonStyle?: React.CSSProperties;
buttonClassName?: string;
}, },
{ {
goMessageList: () => void; goMessageList: () => void;
@ -21,18 +27,29 @@ export default function Render(
> >
) { ) {
const { data } = props; const { data } = props;
const { count } = data; const { count, className, onClick, style, buttonStyle, buttonClassName } =
data;
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
return ( return (
<> <>
<Badge count={count}> <Badge count={count}>
<Button <Button
className={Style.btn} className={classNames(Style.btn, buttonClassName)}
style={buttonStyle}
type="text" type="text"
shape="circle" shape="circle"
icon={<BellOutlined />} icon={
onClick={() => { <BellOutlined
className={classNames(Style.icon, className)}
style={style}
/>
}
onClick={(e) => {
if (typeof onClick === 'function') {
onClick(e);
return;
}
setOpen(true); setOpen(true);
}} }}
/> />

View File

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { Badge } from 'antd-mobile'; import { Badge } from 'antd-mobile';
import classNames from 'classnames';
import { BellOutlined } from '@ant-design/icons'; import { BellOutlined } from '@ant-design/icons';
import { WebComponentProps } from 'oak-frontend-base'; import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../general-app-domain'; import { EntityDict } from '../../../general-app-domain';
@ -13,6 +14,9 @@ export default function Render(
false, false,
{ {
count?: number; count?: number;
onClick?: (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => void;
className?: string;
style?: React.CSSProperties;
}, },
{ {
goMessageList: () => void; goMessageList: () => void;
@ -20,19 +24,22 @@ export default function Render(
> >
) { ) {
const { data, methods } = props; const { data, methods } = props;
const { count } = data; const { count, className, onClick, style } = data;
const { goMessageList } = methods; const { goMessageList } = methods;
return ( return (
<> <Badge content={count || ''}>
<Badge content={count || ''}> <BellOutlined
<BellOutlined className={classNames(Style.icon, className)}
className={Style.icon} style={style}
onClick={() => { onClick={(e) => {
goMessageList(); if (typeof onClick === 'function') {
}} onClick(e);
/> return;
</Badge> }
</> goMessageList();
}}
/>
</Badge>
); );
} }

View File

@ -0,0 +1,265 @@
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;
}

View File

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@ -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>

View File

@ -0,0 +1,4 @@
.ec-canvas {
width: 100%;
height: 100%;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,111 @@
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
}
}

View File

@ -1,6 +1,6 @@
/** index.wxss **/
.container { .container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1;
background-color: var(--oak-bg-color-page); background-color: var(--oak-bg-color-page);
} }