1) 面对可视化需求, 应该选择canvas还是svg?
答: canvas是基于HTMLCanvasElement, 图形是调用api绘制的, 主要是写js。不过, 对于复杂的path,比svg的path稍微步骤多一点, svg只要用字母数字组成string即可。
svg是类似于HTML的, 元素用html拼成, 主要是写html。svg更合适写需要互动的图片, 更方便写交互。
有时候, 我们也会使用div做热力图, 好处是tooltip等很方便。
2) 如何自适应高度和宽度
svg很方便做成自适应的高宽,viewport='x y width height" width相当于把页面等分成width份。
canvas需要用js计算需要的宽度。 例如:
const container = <HTMLCanvasElement>document.getElementByTagName('canvas'); container.width = body.clientWidth; // sreen.width>screen.availWidth>window.outerWidth>window.innerWidth>body.clientWidth (body.clientWidth是页面显示的宽度, 而body.offsetWidth是页面总的高度)(滚动条的宽度 = window.innerWidth - body.clientWidth) const colors = ['red']; const ctx = container.getContext('2d'); const DrawChart = (options) => { this.options = options; this.ctx = options.ctx; this.colors = options.colors; this.draw = () => { this.ctx.save(); this.ctx.strokeStyle = this.colors[0]; this.ctx.strokeRect(0,0,10,10); this.ctx.strokeText('Hello world', 5,5); this.ctx.restore(); } this.clear = () => { this.ctx.save(); this.ctx.clearRect(0,0,10,10); this.ctx.restore(); } } const drawChart = new DrawChart({ctx, colors});
3) 如何加入tooltip?
a. canvas: 其实canvas加入tooltip不是很方便,需要计算监听mouseover/mouseOut的事件, 事件处理是判断计算元素进入范围, 如果进入范围,需要draw这个图形元素。
//e:MouseEvent const clickX = e.pageX - canvas.offsetLeft; const clickY = e.pageY - canvas.offsetTop; const distanceFromCenter = Math.sqrt(Math.pow(circle.x - clickX, 2)+ Math.pow(circle.y - clickY, 2)) // 判断这个点是否在圆圈中 if (distanceFromCenter <= circle.radius) { tooltip(); }
b. 在angular需要处处插值, 插元素, 所以可以使用directive, 插入canvas
@Directive({selector: 'appTooltip'}) class TooltipDirective { @HostBinder('mouseOver', 'event.target') public onMouseOver(event) { const canvas = document.createElement('canvas'); event.appendChild(canvas); canvas.id = 'myCanvas'; canvas.width = '300'; canvas.height = '300'; const chart = this.drawchart(); chart.draw(); } private drawchart(){ const ctx = document.getElementById('myCanvas').getContext('2d'); const Circle = (options) =>{ this.ctx = options.ctx; this.draw = () => { this.ctx.save(); this.ctx.fillRect(0,0,100,100); this.ctx.restore(); } } const circle = new Circle({ctx}); return circle; } }
c. <div title='ss'></div>
4) 如何加入动画?
react automation