Open licjing opened 5 years ago
一个页面有多个图表,有的图表有时候只画了一半的大小
遇到了同样的问题,使用分辨率 pixelRatio
放大后,使用样式的宽、高缩小不回来。
@simaQ
可以否帮忙看一下:
根据 canvas 文档所述,将画布的宽、高属性按照设备的分辨率放大后,再通过样式的宽、高缩小,可以在高 dpr 下取得更细腻的显示。但是这样做了以后,支付宝开发工具中图表被放大很多(详见下面的截图,右侧微信小程序是可以正常显示的)。
因为是采用 Megalo 写的,不能确定是哪里出了问题。如果将 ctx.scale(pixelRatio, pixelRatio)
去掉,支付宝开发工具可以正常显示。
// 如果需要在高 dpr 下取得更细腻的显示,需要先将 canvas 用属性设置放大,用样式缩小,例如
// <!-- getSystemInfoSync().pixelRatio === 2 -->
// <canvas width="200" height="200" style="width:100px;height:100px;"/>
const pixelRatio = my.getSystemInfoSync().pixelRatio;
_this.width = rect[0].width * pixelRatio; // 按设备分辨率放大 canvas 的宽、高属性
_this.height = rect[0].height * pixelRatio;
const ctx = my.createCanvasContext(_this.canvasId);
ctx.scale(pixelRatio, pixelRatio); // alipay: 按设备分辨率放大 canvas 属性后,通过样式缩小不回来
const canvas = new F2.Renderer(ctx);
_this.canvas = canvas;
if (typeof callback === 'function') {
_this.chart = callback(
canvas,
rect[0].width,
rect[0].height,
F2
);
} else if (_this.opts && typeof _this.opts.onInit === 'function') {
_this.chart = this.opts.onInit(
canvas,
rect[0].width,
rect[0].height,
F2
);
}
@b2nil 如果是使用 native canvas 版本的话,按照之前这块的负责人给我的信息,是直接在 native canvas 层解决了不同分辨率的显示问题,这样的话,在使用 my-f2 绘制图表时,就不需要再做 canvas.scale 了,你可以看下使用 canvas native 渲染的图表的例子: https://github.com/antvis/mini-program-f2-demos/tree/for-native-test/pages/charts/area,如果使用的 native canvas,高清以及事件都不用在代码中处理了
@licjing 能提供使用的 my-f2 版本吗?另外这种现象是在 IDE 中还是真机上,最好能提供完整的可复现的代码,包括 axml,js 等文件
@licjing 能提供使用的 my-f2 版本吗?另外这种现象是在 IDE 中还是真机上,最好能提供完整的可复现的代码,包括 axml,js 等文件
"dd-charts": "^1.0.5"
axss: .pages{ padding: 12px; font-size: 13px; } canvas{ width: 100%; height: 100%; } .Demos1{ width: 100%; height: 200px; } .Demos2{ width: 100%; height: 200px;
} .Demos3{ width: 100%; height: 100px; } axml:
js: import F2 from '@antv/my-f2'; const value1 = [ { date: "2017-06-05", value: 116 }, { date: "2017-06-06", value: 129 }, { date: "2017-06-07", value: 135 }, { date: "2017-06-08", value: 86 }, { date: "2017-06-09", value: 73 }, { date: "2017-06-10", value: 85 }, { date: "2017-06-11", value: 73 }, { date: "2017-06-12", value: 68 }, { date: "2017-06-13", value: 92 }, { date: "2017-06-14", value: 130 }, { date: "2017-06-15", value: 245 }, { date: "2017-06-16", value: 139 }, { date: "2017-06-17", value: 115 }, { date: "2017-06-18", value: 111 }, { date: "2017-06-19", value: 309 }, { date: "2017-06-20", value: 206 }, { date: "2017-06-21", value: 137 }, { date: "2017-06-22", value: 128 }, { date: "2017-06-23", value: 85 }, { date: "2017-06-24", value: 94 }, { date: "2017-06-25", value: 71 }, { date: "2017-06-26", value: 106 }, { date: "2017-06-27", value: 84 }, { date: "2017-06-28", value: 93 }, { date: "2017-06-29", value: 85 }, { date: "2017-06-30", value: 73 }, { date: "2017-07-01", value: 83 }, { date: "2017-07-02", value: 125 }, { date: "2017-07-03", value: 107 }, { date: "2017-07-04", value: 82 }, ]; const value2 = [{ age: '18岁以下', value: 0.20 }, { age: '18-24岁', value: 0.10 }, { age: '25-29岁', value: 0.26 }, { age: '30-34岁', value: 0.14 }, { age: '35-39岁', value: 0.13 }, { age: '40-49岁', value:0.15 }, { age: '50岁', value:0.02 }] const value3 =[{ "candy":"", "type":"钉钉", "value":446, "percent":0.24030172413793102 },{ "candy":"", "type":"非常道", "value":672, "percent":0.3620689655172414 },{ "candy":"", "type":"脉脉", "value":273, "percent":0.1470905172413793 },{ "candy":"", "type":"今目标", "value":204, "percent":0.10991379310344827 },{ "candy":"", "type":"其他", "value":261, "percent":0.140625 }];
Page({
onLoad(query) {
// 页面加载
console.info(Page onLoad with query: ${JSON.stringify(query)}
);
},
onReady() {
// 页面加载完成
this.Demos1();
this.Demos2();
this.Demos3();
},
onShow() {
// 页面显示
},
onHide() {
// 页面隐藏
},
onUnload() {
// 页面被关闭
},
onTitleClick() {
// 标题被点击
},
onPullDownRefresh() {
// 页面被下拉
},
onReachBottom() {
// 页面被拉到底部
},
onShareAppMessage() {
// 返回自定义分享信息
return {
title: 'My App',
desc: 'My App description',
path: 'pages/index/index',
};
},
Demos1(){
dd.createSelectorQuery().select('#Demos1').boundingClientRect().exec((res) => {
const pixelRatio = my.getSystemInfoSync().pixelRatio;
const canvasWidth = res[0].width;
const canvasHeight = res[0].height;
// 高清解决方案
this.setData({
width: canvasWidth pixelRatio,
height: canvasHeight pixelRatio
});
const myCtx = my.createCanvasContext('Demos1');
myCtx.scale(pixelRatio, pixelRatio); // �必要!按照设置的分辨率进行放大
let canvas = new F2.Renderer(myCtx);
this.Demos1Fn(canvas, canvasWidth,canvasHeight);
});
},
Demos1Fn(canvas, width, height){
var that = this;
var Global = F2.Global;
var chart= new F2.Chart({
el: canvas,
width,
height
});
chart.source(value1, {
value: {
tickCount: 5,
min: 0
},
date: {
type: 'timeCat',
tickCount: 4
}
})
chart.legend({
position:'top',
custom: true,
clickable: true,
items: [ {
name: that.data.currentName,
value:0,
marker: 'square',
fill: 'blue'
}],
checked: true,
})
chart.tooltip({
alwaysShow:true,
custom: false,
background:{
radius: 2,
fill: '#ccc',
padding: [ 6, 10 ]
},
onChange(ev){
const legend = chart.get('legendController').legends.top[0];
const tooltipItems = ev.items;
const legendItems = legend.items;
const map = {};
legendItems.map(item => {
map[item.name] = {...item};
});
tooltipItems.map(item => {
map[that.data.currentName].value = item.value;
});
legend.setItems(Object.values(map));
},
onClick(ev){
},
onHide(tooltip) {
const legend = chart.get('legendController').legends.top[0];
}
})
chart.axis('date', {
label(text, index, total) {
const textCfg = {};
if (index === 0) {
textCfg.textAlign = 'left';
}
if (index === total - 1) {
textCfg.textAlign = 'right';
}
return textCfg;
}
});
chart.line().position('date*value').shape('smooth');
chart.render()
},
Demos2(){
dd.createSelectorQuery().select('#Demos2').boundingClientRect().exec((res) => {
// 获取分辨率
const pixelRatio = my.getSystemInfoSync().pixelRatio;
// 获取画布实际宽高
const canvasWidth = res[0].width;
const canvasHeight = res[0].height;
// 高清解决方案
this.setData({
Demos2width: canvasWidth pixelRatio,
Demos2height: canvasHeight pixelRatio
});
const myCtx = my.createCanvasContext('Demos2');
myCtx.scale(pixelRatio, pixelRatio); // �必要!按照设置的分辨率进行放大
const canvas = new F2.Renderer(myCtx);
this.Demos2Fn(canvas, res[0].width, res[0].height);
});
},
Demos2Fn(canvas, width, height) {
let that = this;
const Global = F2.Global;
const chart = new F2.Chart({
el: canvas,
width,
height
});
chart.source(value2, {
value: {
tickCount: 5
}
});
chart.coord({
transposed: false
});
chart.axis('age', {
line: Global._defaultAxis.line,
grid: null
});
chart.axis('value', {
line: null,
grid: Global._defaultAxis.grid,
label: null
});
value2.map(function(obj) {
chart.guide().text({
position: [obj.age, obj.value],
content: (obj.value 100).toFixed(0) + '%',
style: {
textBaseline: 'bottom',
textAlign: 'center'
},
offsetY: -2
});
});
chart.tooltip({
custom: true,
})
chart.interval().position('agevalue');
chart.render();
},
Demos3(){
dd.createSelectorQuery().select('#Demos3').boundingClientRect().exec((res) => {
// 获取分辨率
const pixelRatio = my.getSystemInfoSync().pixelRatio;
// 获取画布实际宽高
const canvasWidth = res[0].width;
const canvasHeight = res[0].height;
// 高清解决方案
this.setData({
Demos3width: canvasWidth pixelRatio,
Demos3height: canvasHeight pixelRatio
});
const myCtx = my.createCanvasContext('Demos3');
myCtx.scale(pixelRatio, pixelRatio); // �必要!按照设置的分辨率进行放大
const canvas = new F2.Renderer(myCtx);
this.Demos3Fn(canvas, canvasWidth, canvasHeight);
});
},
Demos3Fn(canvas, width, height){
let colors = {
'钉钉': '#399afa',
'非常道': '#59aafa',
'脉脉': '#94c8fc',
'今目标': '#d6eafe',
'其他': '#ededee'
};
const Shape = F2.Shape;
const Util = F2.Util;
const G = F2.G;
function formatter(val) {
return (val 100).toFixed(0) + '%';
}
const ddChart = new F2.Chart({
el: canvas,
width,
height
});
Shape.registerShape('interval', 'text', {
draw: function draw(cfg, container) {
var points = this.parsePoints(cfg.points);
var style = {
fill: cfg.color,
z: true // 需要闭合
};
var shapes = [];
var intervalWidth = points[1].x - points[0].x;
var interval = container.addShape('rect', {
attrs: Util.mix({
x: points[0].x,
y: points[0].y,
width: intervalWidth,
height: -20
}, style)
}); // 绘制柱形
shapes.push(interval);
var origin = cfg.origin._origin; // 获取对应的原始数据
var textOffsetX = 4;
var text = new G.Shape.Text({
attrs: {
x: points[0].x + textOffsetX,
y: (points[0].y + points[3].y) / 2,
text: formatter(origin.percent),
textAlign: 'start',
textBaseline: 'middle',
fontSize: 10
}
});
var textWidth = text.getBBox().width;
if (textWidth + textOffsetX < intervalWidth) {
container.add(text);
shapes.push(text);
}
return shapes;
}
});
ddChart.clear()
ddChart.source(value3, {
value: {
tickCount: 5,
min: 0,
max: 1,
nice: false,
formatter: formatter
}
})
ddChart.coord({
transposed: true
})
ddChart.legend({
marker: 'square',
clickable: false,
position:'bottom',
itemWidth:'30%',
offsetY: -10,
offsetX: 10,
});
ddChart.tooltip(false);
ddChart.axis('percent', false)
ddChart.interval().position('candypercent').color('type', function(val) {
return colors[val];
}).adjust('stack').shape('text');
ddChart.render()
}
});
@simaQ 谢谢。
所以这个问题解决了吗。。。
@TianBM 没有呢
@licjing 好吧,我是钉钉E应用遇到了类似问题,找了下原因是在my-F2的Scale方法出的问题
@TianBM 我也是钉钉E应用遇到的,您有什么解决方案吗?
@licjing 暂时没有
@TianBM 如果后续有解决方法,共享一下,谢谢~
import F2 from '@antv/my-f2';
Component({ mixins: [{}], data: { width: 0, height: 0 }, props: { canvasId: 'f2-canvas', onDraw: function onDraw() {} }, didUpdate: function didUpdate(prevProps, prevData) { console.log(prevProps, this.props, prevData, this.data); }, didMount: function didMount() { this.init(); }, didUnmount: function didUnmount() {},
methods: {
init: function init(cb) {
var me = this;
var canvasId = me.props.canvasId;
dd.createSelectorQuery().select('#' + canvasId).boundingClientRect().exec(function (res) {
// 获取分辨率
var pixelRatio = dd.getSystemInfoSync().pixelRatio;
// 获取画布实际宽高
var canvasWidth = res[0].width;
var canvasHeight = res[0].height;
me.setData({
width: canvasWidth * pixelRatio,
height: canvasHeight * pixelRatio
});
var myCtx = dd.createCanvasContext(canvasId);
//可能导致比例失调
myCtx.scale(pixelRatio, pixelRatio);
var canvas = new F2.Renderer(myCtx);
me.canvas = canvas;
me.chart = new F2.Chart({
el: canvas,
width:canvasWidth,
height:canvasHeight
});
if (typeof cb === 'function') {
me.props.onDraw(me.chart, F2);
} else if (me.props && me.props.onDraw) {
me.props.onDraw(me.chart, F2);
}
});
},
touchStart: function touchStart(e) {
if (this.canvas) {
this.canvas.emitEvent('touchstart', [e]);
}
},
touchMove: function touchMove(e) {
if (this.canvas) {
this.canvas.emitEvent('touchmove', [e]);
}
},
touchEnd: function touchEnd(e) {
if (this.canvas) {
this.canvas.emitEvent('touchend', [e]);
}
}
}
});
@licjing 我定位的是钉钉封装的dd-charts组件中的myCtx.scale(pixelRatio, pixelRatio);语句可能导致比例失调的问题
@TianBM en
参考下这个: https://www.yuque.com/antv/f2/miniprogram#comment-147139
在 setData 的回调里绘制图表:
this.setData({
width: canvasWidth * pixelRatio,
height: canvasHeight * pixelRatio
}, () => {
const myCtx = my.createCanvasContext('radar'); // "radar" 替换为你自己定义的 canvas 的 id
myCtx.scale(pixelRatio, pixelRatio); // 必要!按照设置的分辨率进行放大
const canvas = new F2.Renderer(myCtx);
this.canvas = canvas;
drawChart(canvas, res[0].width, res[0].height);
});
有用,看来确实是setData异步的问题
@simaQ 请问是怎么解决多个图表多个是一大一小的问题的吗
@thefireoftheblue 解决了吗
@simaQ
可以否帮忙看一下:
根据 canvas 文档所述,将画布的宽、高属性按照设备的分辨率放大后,再通过样式的宽、高缩小,可以在高 dpr 下取得更细腻的显示。但是这样做了以后,支付宝开发工具中图表被放大很多(详见下面的截图,右侧微信小程序是可以正常显示的)。
因为是采用 Megalo 写的,不能确定是哪里出了问题。如果将
ctx.scale(pixelRatio, pixelRatio)
去掉,支付宝开发工具可以正常显示。截图
代码
// 如果需要在高 dpr 下取得更细腻的显示,需要先将 canvas 用属性设置放大,用样式缩小,例如 // <!-- getSystemInfoSync().pixelRatio === 2 --> // <canvas width="200" height="200" style="width:100px;height:100px;"/> const pixelRatio = my.getSystemInfoSync().pixelRatio; _this.width = rect[0].width * pixelRatio; // 按设备分辨率放大 canvas 的宽、高属性 _this.height = rect[0].height * pixelRatio; const ctx = my.createCanvasContext(_this.canvasId); ctx.scale(pixelRatio, pixelRatio); // alipay: 按设备分辨率放大 canvas 属性后,通过样式缩小不回来 const canvas = new F2.Renderer(ctx); _this.canvas = canvas; if (typeof callback === 'function') { _this.chart = callback( canvas, rect[0].width, rect[0].height, F2 ); } else if (_this.opts && typeof _this.opts.onInit === 'function') { _this.chart = this.opts.onInit( canvas, rect[0].width, rect[0].height, F2 ); }
你好,问题解决了吗,我微信小程序遇到了同样的问题,使用F2的pixelRatio导致画布大小变大了,使用myCtx.scale图表没有变清晰。
暂时没有解决 暂时是把高清操作去掉了。后面再想办法。应该是哪里异步了,需要去改my-f2那个node_module。后面你如果有办法了 也请告知一声啊
------------------ 原始邮件 ------------------ 发件人: "Yrobot"<notifications@github.com>; 发送时间: 2020年5月7日(星期四) 中午1:22 收件人: "antvis/my-f2"<my-f2@noreply.github.com>; 抄送: "洪晖旭"<709619407@qq.com>;"Comment"<comment@noreply.github.com>; 主题: Re: [antvis/my-f2] 一个页面有多个图表,有的图表有可能只画了一半的大小 (#15)
@simaQ
可以否帮忙看一下:
根据 canvas 文档所述,将画布的宽、高属性按照设备的分辨率放大后,再通过样式的宽、高缩小,可以在高 dpr 下取得更细腻的显示。但是这样做了以后,支付宝开发工具中图表被放大很多(详见下面的截图,右侧微信小程序是可以正常显示的)。
因为是采用 Megalo 写的,不能确定是哪里出了问题。如果将 ctx.scale(pixelRatio, pixelRatio) 去掉,支付宝开发工具可以正常显示。
截图
代码 // 如果需要在高 dpr 下取得更细腻的显示,需要先将 canvas 用属性设置放大,用样式缩小,例如 // <!-- getSystemInfoSync().pixelRatio === 2 --> // <canvas width="200" height="200" style="width:100px;height:100px;"/> const pixelRatio = my.getSystemInfoSync().pixelRatio; _this.width = rect[0].width pixelRatio; // 按设备分辨率放大 canvas 的宽、高属性 _this.height = rect[0].height pixelRatio; const ctx = my.createCanvasContext(_this.canvasId); ctx.scale(pixelRatio, pixelRatio); // alipay: 按设备分辨率放大 canvas 属性后,通过样式缩小不回来 const canvas = new F2.Renderer(ctx); _this.canvas = canvas; if (typeof callback === 'function') { _this.chart = callback( canvas, rect[0].width, rect[0].height, F2 ); } else if (_this.opts && typeof _this.opts.onInit === 'function') { _this.chart = this.opts.onInit( canvas, rect[0].width, rect[0].height, F2 ); }
你好,问题解决了吗,我微信小程序遇到了同样的问题,使用F2的pixelRatio导致画布大小变大了,使用myCtx.scale图表没有变清晰。
— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.
@Yrobot
我当时遇到的是在支付宝小程序上,钉钉不知道具体情况,不知道是不是一样。 跟上面 @huixu123 说的那样,可以暂时把高清操作去掉。
根据 @simaQ 描述,native-canvas 版本似乎没那么复杂。于是我当时使用了 my-f2 native-canvas 分支中的代码。
然后遇到了这个问题: native canvas 事件:context.removeEventListener is not a function。 具体的 [merged PR]:(https://github.com/antvis/my-f2/commit/f7d2f9f90c41b5804e4756d7c6bd984997a7736f)
太久没有跟进这个项目了,不知道后来的进展怎么样。今天看一下,我这个 PR 也被改回来了。 如果喜欢折腾的话,看看改改 my-f2 的源码能不能解决。
@Yrobot
我当时遇到的是在支付宝小程序上,钉钉不知道具体情况,不知道是不是一样。 跟上面 @huixu123 说的那样,可以暂时把高清操作去掉。
根据 @simaQ 描述,native-canvas 版本似乎没那么复杂。于是我当时使用了 my-f2 native-canvas 分支中的代码。
然后遇到了这个问题: native canvas 事件:context.removeEventListener is not a function。 具体的 [merged PR]:(f7d2f9f)
太久没有跟进这个项目了,不知道后来的进展怎么样。今天看一下,我这个 PR 也被改回来了。 如果喜欢折腾的话,看看改改 my-f2 的源码能不能解决。
感谢回复,我目前已经解决高分辨率的问题,下面会分享一下
@b2nil @huixu123 我这边放弃使用F2自带的pixelRatio,用canvasContext.scale去处理了 ps:用的是微信kbone开发(别用kbone官方方法获取canvasDOM,很坑,用querySelector获取)
// DOM
<canvas
type="2d"
style={{ width: width + 'px', height: height + 'px' }}
id={cnvasID}
canvas-id={cnvasID}
key={cnvasID}
/>
// JS 绘制逻辑
const draw = canvas => {
const ctx = canvas.getContext('2d')
ctx.restore()
canvas.width = width * pixelRatio
canvas.height = height * pixelRatio
ctx.scale(pixelRatio, pixelRatio)
F2.Global.pixelRatio = 1
F2.Global.fontFamily = 'sans-serif'
const chart = new F2.Chart({
context: ctx,
width: width,
height: height
})
doChart(chart)
}
@Yrobot 我当时遇到的是在支付宝小程序上,钉钉不知道具体情况,不知道是不是一样。 跟上面 @huixu123 说的那样,可以暂时把高清操作去掉。 根据 @simaQ 描述,native-canvas 版本似乎没那么复杂。于是我当时使用了 my-f2 native-canvas 分支中的代码。 然后遇到了这个问题: native canvas 事件:context.removeEventListener is not a function。 具体的 [merged PR]:(f7d2f9f) 太久没有跟进这个项目了,不知道后来的进展怎么样。今天看一下,我这个 PR 也被改回来了。 如果喜欢折腾的话,看看改改 my-f2 的源码能不能解决。
感谢回复,我目前已经解决高分辨率的问题,下面会分享一下
确实是this.setData()异步了。改下my-f2组件的代码 。把this.props.onInit()挪到的this.setData()的回调里可以解决这个问题。后面需要把这个组件从node_modules里挪出来 this.setData({ id, width: width pixelRatio, height: height pixelRatio },()=>{ this.props.onInit(F2, { context, width, height, pixelRatio }); }); //this.props.onInit(F2, { context, width, height, pixelRatio });
再提个PR改一下?
我就想知道有人用interaction这个接口吗,我用不了,没作用,滚动条直接报错
一个页面有多个图表,有的图表有可能只画了一半的大小 dd.createSelectorQuery().select('#xxx').boundingClientRect().exec((res) => { const pixelRatio = my.getSystemInfoSync().pixelRatio; const canvasWidth = res[0].width; const canvasHeight = res[0].height; // 高清解决方案 this.setData({ userChartWidth: canvasWidth pixelRatio, userChartHeight: canvasHeight pixelRatio }); const myCtx = my.createCanvasContext('xxx'); myCtx.scale(pixelRatio, pixelRatio); // �必要!按照设置的分辨率进行放大 let canvas = new F2.Renderer(myCtx); this.chart = canvas; this.drawChart(canvas, canvasWidth,canvasHeight); });