【 Realization of my own visualization engine 01】 Understanding Canvas 【 realization of my own Visualization framework engine 02】 Abstract image elements 【 Realization of my own visualization engine 03】 Construction of basic metalibrary 【 Realization of my own visualization engine 04】 Image elements animation 【 Realization of my own visualization engine 05】 interaction and events [Realize my own visualization engine 06] broken line chart [realize my own visualization engine 07] Bar chart [Realize my own visualization engine 08] Bar chart [Realize my own visualization engine 09] pie chart [Realize my own visualization engine 10] Scatter chart [Realize my own visualization engine 11] Radar chart [Achieve your own visualization engine 12] K-line [achieve your own visualization engine 13] Dashboard [achieve your own visualization engine 14] map [achieve your own visualization engine 15] diagram

preface

Gauge is a kind of quasi materialized chart. The scale represents the measure, the pointer represents the dimension, and the pointer Angle represents the value. The dashboard chart is like a car speedometer, with a circular dial and corresponding scale, and a pointer pointing to the current value. This section provides the implementation ideas of two types of dashboards. Dashed line type= dashboard.type.stroke

render() {
    return<DashBoard value={0.2} // Scale deflection Angle, the value ranges from 0 to 1 className="chart"
        style={{
          pointColor: '# 333333'// linearGradient: [// [0,'#058F05'[0.3], / /,'#15AF05'[0.5], / /,'#DCD313'[0.8], / /,'#AE1315'[1], / /,'#9E0305'[//], // gradienttype: DashBoard.TYPE.FILL,
          graduation: ['Strong buy'.'buy'.A 'flat'.'sell'.'Strong sell'], // scale string color:'# 999999'}}} / >)Copy the code

Dashboard layer

As can be seen from the renderings, the dashboard layer can be composed of a few simple basic layers: Ring, triangle pointer, and scale (Line and Text). Once we have identified the basic graphics, we can set the properties of the basic graphics to combine them into the images we need. We determined that the Angle of the instrument ring was 150°~390°, and the Angle of the pointer offset was calculated according to the outside property value value of the isosceles triangle rotation=-120° + value * 240°. The meter layer source code is as follows:

make() { this.childs.splice(0, this.childs.length); Const raduis = this.height > this.width? this.width / 2 : this.height / 2; / / dashboardif(this.type === dashboard.type.fill) {// circleletRing = new ring (this.canvas, {linearGradient: this.linearGradient, // linearGradient: this.color, position: New Point(this.width / 2, raduis * 0.45), // Gradius: raduis * 0.9, // Raduis * 0.75, // small radius of ringtype: Ring.TYPE.FILL,
        startAngle: 150,
        endAngle: 390,
      });
      this.addChild(ring);
    } else{/ / arcletRing = new Arc(this.canvas, {linearGradient: this.Lineargradient, color: this.color, radius: raduis * 0.825, position: New Point(this.width / 2, raduis * 0.45), lineDash: [10, 5], // set to dashed lineWidth: raduis * 0.15, // 150, endAngle: 390, }); this.addChild(ring); } // Triangle pointerlet angle = new Polygon(this.canvas, {
      type: polygon.type. FILL, position: new Point(this.width / 2, raduis * 0.45), color: polygon.type. FILL, position: new Point(this.width / 2, raduis * 0.45), color: This.pointcolor,}, [new Point(this.width / 2-10, raduis * 0.45), new Point(this.width / 2 + 10, raduis * 0.45), new Point(this.width / 2, raduis) ]); Const valueAngle = -120 + this.value * 240; Rotation = valueAngle; const angleStep = 240 / (this.graduation.length - 1); // Add a scale linefor (leti = 0; i < this.graduation.length; i++) {letcolor = this.color; // const Angle = (210-i * angleStep) / 180 * math.pi; // If the scale value exceeds value, change the color of the scale line to the selected colorif((1 - this.value) * 240 - 30 < (210 - i * angleStep) ) { color = this.selectColor; } // Scale lineletline = new Line(this.canvas, { position: New Point(this.width / 2 + raduis * 0.65 * math. cos(Angle), raduis * 0.45 + raduis * 0.65 * math. sin(Angle)), to: New Point(this.width / 2 + raduis * 0.75 * math. cos(Angle), raduis * 0.45 + raduis * 0.75 * math. sin(Angle)), color, lineWidth: 1, }); // Calibration const text = new text (this.canvas, {text: this.graduation[I], size: this.fontSize, color, textAlign:'center', position: New Point(this.width / 2 + raduis * 0.6 * math. cos(Angle), raduis * 0.45 + raduis * 0.6 * math. sin(Angle))}); this.addChild(line, text); } this.addChild(angle); // Fill the selected part of the colorif (this.linearGradient.length === 0) {
      if (this.type === DashBoard.TYPE.FILL) {
        letselectRing = new Ring(this.canvas, { color: this.selectColor, position: New Point(this.width / 2, Raduis * 0.45), longRadius: Raduis * 0.95, shortRadius: Raduis * 0.95,type: Ring.TYPE.FILL,
          startAngle: 150,
          endAngle: 150 + this.value * 240,
        });
        this.addChild(selectRing);
      } else {
        letSelectRing = new Arc(this.canvas, {color: this.selectColor, radius: raduis * 0.825, position: New Point(this.width / 2, raduis * 0.45), lineDash: [10, 5], lineWidth: raduis * 0.15, startAngle: 150, endAngle: 150 + this.value * 240, }); this.addChild(selectRing); }}}Copy the code

The React to encapsulate

The React wrapper requires the DOM to be mounted, so we build our layers in the lifecycle componentDidMount function.

componentDidMount () {
    const { style = {}, value =  0 } = this.props;
    this.canvas = new Canvas({
      ele: this.ref.current,
      canAction: false}); this.dash = new DashBoard(this.canvas, style, value); this.canvas.addChild(this.dash); this.dash.make(); this.canvas.paint(); }Copy the code