两个圆画切线 canvas charts笔记

119 阅读4分钟

image.png

 初始化值
    const ref = useRef(null);
    const canvasRef =useRef(null);

      const circle1Radius = 75; //半径
    const circle2Radius = 60;//半径
        const [circle1Center,setcircle1Center] =useState<any>( { x: 243, y: 75 }) // 圆1的圆心坐标
    const [circle2Center,setcircle2Center] =useState<any>( { x: 730, y: 75 }) // 圆2的圆心坐标
    //获取cavas
        var canvas = document.getElementById('targetcanvas');
  
        useEffect(() => {
      
        const element = document.getElementById('divpie');
            if (element) {
              const width = element.offsetWidth;
              console.log('获取2个圆的父元素的宽度:', width); 
              //计算2个 圆的x值的中心点。 每个圆是占父元素的50%。以左下角定点为0点位置  x=0 ,y=0  。 那么每个圆的中心点 。 y值是大圆的半径高度值。 此demo为75
              let leftpie =  width/4
             let  rightpie=width/2+width/4
                setcircle1Center(
                { x: leftpie, y: 75 }
                 )

                 setcircle2Center({
                    x: rightpie, y: 75 
                 })

                 console.log('Width:', width,'leftpie',leftpie,'rightpie',rightpie);
            
            }
    }, [])
//如果画切线

声明canvas
   var ctx = canvas.getContext("2d");
        // 获取父元素的宽度
        // 设置canvas宽度和高度与其兄弟元素相同
        const parentWidth = canvas.parentNode.offsetWidth;
        console.log('parentWidth',parentWidth)
        // const parentHeight = canvas.parentNode.offsetHeight-24;
        const parentHeight =150;
        canvas.width = parentWidth;
        canvas.height = parentHeight;


// 划线函数
   const drawLine=(ctx, pointStart, pointEnd) =>{
        console.log(ctx, pointStart, pointEnd)
        ctx.beginPath();
        ctx.moveTo(pointStart.x, pointStart.y);
        ctx.lineTo(pointEnd.x, pointEnd.y);
        ctx.stroke();
      }
  
  
  //计算坐标点
  
   const calcQieDian=(c1, r1, c2,  r2)=> {
        //圆心之间的距离
        let d = Math.sqrt(Math.pow(c1.x - c2.x, 2) + Math.pow(c1.y - c2.y, 2));
        //外公切线与连心线夹角的角度
        let theta = Math.acos((r1 - r2) / d);
        let vc1c2 = { x: c2.x - c1.x, y: -c2.y + c1.y }; //屏幕坐标系与笛卡尔坐标系是y轴是反着的
        let radC1C2 = Math.acos(vc1c2.x / Math.sqrt(Math.pow(vc1c2.x, 2) + Math.pow(vc1c2.y, 2)));
  
        if (c2.y <= c1.y) {
          //大圆上的切点
          let p1 = { x: c1.x + Math.cos(theta + radC1C2) * r1, y: c1.y - Math.sin(theta + radC1C2) * r1 };
          let p2 = { x: c1.x + Math.cos(theta - radC1C2) * r1, y: c1.y + Math.sin(theta - radC1C2) * r1 };
          //小圆上的切点
          let p3 = { x: c2.x + Math.cos(theta + radC1C2) * r2, y: c2.y - Math.sin(theta + radC1C2) * r2 };
          let p4 = { x: c2.x + Math.cos(theta - radC1C2) * r2, y: c2.y + Math.sin(theta - radC1C2) * r2 };
          return { p1: p1, p2: p2, p3: p3, p4: p4 };
        } else {
          radC1C2 = Math.PI - radC1C2;
          //大圆上的切点
          let p1 = { x: c1.x + Math.cos(Math.PI - theta - radC1C2) * r1, y: c1.y + Math.sin(Math.PI - theta - radC1C2) * r1 };
          let p2 = { x: c1.x + Math.cos(Math.PI - (theta - radC1C2)) * r1, y: c1.y - Math.sin(Math.PI - (theta - radC1C2)) * r1 };
          //小圆上的切点
          let p3 = { x: c2.x + Math.cos(Math.PI - theta - radC1C2) * r2, y: c2.y + Math.sin(Math.PI - theta - radC1C2) * r2 };
          let p4 = { x: c2.x + Math.cos(Math.PI - (theta - radC1C2)) * r2, y: c2.y - Math.sin(Math.PI - (theta - radC1C2)) * r2 };
          return { p1: p1, p2: p2, p3: p3, p4: p4 };
        }
      }
      
     
    
      
     // 调用
      // 2条线的4个值。
      { x1,y1},左侧圆中心点 
      r1,左侧圆半径
      { x2,y2},右侧圆中心点 
      r2,右侧圆半径
      const fourdian= calcQieDian(
        circle1Center,
        circle1Radius,
        circle2Center,
        circle2Radius
      )
      
     
        ctx.lineWidth = 2 // 线宽
        ctx.stroke() // 线路
        ctx.strokeStyle = 'blue'; //颜色
       //划线 
        drawLine(ctx, fourdian.p1,fourdian.p3);
        drawLine(ctx, fourdian.p2, fourdian.p4);
      
  以上是切线的 大概逻辑


如果是算一部分数据 到右侧是值
以本图为例
左侧蓝色区域的图 到右侧图的线。 为红线部分 
import React, { useState, useEffect, useContext, useRef } from "react";
import ECOption from "_s/libs/echarts-config.d.ts";
import echarts from "_s/libs/echarts-config.ts";
import ReactEChartsCore from "echarts-for-react/lib/core";
const { Option } = Select
const OverduePie = () => {
    const ref = useRef(null);
    const canvasRef = useRef(null);
   const circle1Radius = 75; //大圆半径
    const circle2Radius = 60;  //小圆半径
     const [delayOverdue, setDelayOverdue] = useState<any>([]) // 大饼图
    const [dueOverdue, setDueOverdue] = useState<any>([]) // 小饼图
    const [circle1Center, setcircle1Center] = useState<any>({ x: 243, y: 75 }) // 圆1的圆心坐标
    const [circle2Center, setcircle2Center] = useState<any>({ x: 730, y: 75 }) // 圆2的圆心坐标
     var canvas = document.getElementById('targetcanvas'); //获取canvas
   useEffect(() => {
    //初始化时候获取元素宽度。 并且将父级元素的宽高设置给大小圆的坐标点。 找到中心点
        const element = document.getElementById('divpie');
        if (element) {
            const width = element.offsetWidth;
            console.log('Width:', width);
            let leftpie = width / 4
            let rightpie = width / 2 + width / 4
            setcircle1Center(
                { x: leftpie, y: 75 }
            )

            setcircle2Center({
                x: rightpie, y: 75
            })

            console.log('Width:', width, 'leftpie', leftpie, 'rightpie', rightpie);

        }
    }, [])
   // 接口返回数据的时候处理图表和canvas
     const { loading: loadMARKET, run: runMARKET } = useRequest(GET_SERVICE_STAGING_OVERDUE_MARKET, {
        manual: true,
        onSuccess: (list: { error_code: number; data: any; msg: any }) => {
            if (list.error_code != 0) {
                return
            }

            setDelayOverdue(list.data.delayOverdue)
            setDueOverdue(list.data.dueOverdue)
            console.log('图表返回', list)
//这部分是旋转角度。 让图表以中心展示蓝色区域
            const pieChart = calculatePieChartAngles(list.data.dueOverdue);

            console.log('pieChart=', pieChart)
            let chpre = parseInt((parseInt(pieChart[0].angle) / 2).toString())
            console.log('chpre', chpre)
            let roratedeg = parseInt(parseInt(chpre / 26))
            console.log('角度问题===', parseInt(pieChart[0].angle), chpre, roratedeg);
            //这部分是旋转角度。 让图表以中心展示蓝色区域
//这部分是获取左侧大图的2部分数据各占饼图的多少。算角度和坐标点
            const pievalueAll = pieChart[0].value + pieChart[1].value
            const leftvalue = pieChart[0].value
            const rightvalue = pieChart[1].value
            console.log('总值', pievalueAll)
            const firstPartRatio = leftvalue / pievalueAll; // 第一个部分的占比
            const secondPartRatio = rightvalue / pievalueAll; // 第二个部分的占比
            const arr1Angle = firstPartRatio * 360; // arr1所占的角度
            const arr2Angle = secondPartRatio * 360; // arr2所占的角度
            //大图最大的部分就是切线顶点部分。所以测算如果是90 那就直接设置为上下2个定点。 
            let arr1half: any = ''
            if (arr1Angle / 2 > 90) {
                arr1half = 90
            } else {
                arr1half = arr1Angle / 2
            }

            let arr2half = 360 - arr1half
            const arr1Rad = (arr1half * Math.PI) / 180; // arr1所占的角度转换为弧度表示
            const arr2Rad = (arr2half * Math.PI) / 180;// arr2所占的角度转换为弧度表示
            console.log('arr1Angle', arr1Angle, arr1Rad,)
            console.log('arr2Angle', arr2Angle, arr2Rad)

            const leftpiex = circle1Center.x + Math.cos(arr1Rad) * circle1Radius;
            const leftpiey = circle1Center.y + Math.sin(arr1Rad) * circle1Radius;
            setleftpiex(circle1Center.x + Math.cos(arr2Rad) * circle1Radius)
            setleftpiey(circle1Center.y + Math.sin(arr2Rad) * circle1Radius)
            console.log('leftpiex,leftpiey', leftpiex, leftpiey)
            const rightpiex = circle1Center.x + Math.cos(arr2Rad) * circle1Radius;
            const rightpiey = circle1Center.y + Math.sin(arr2Rad) * circle1Radius;
            setleftpiex(circle1Center.x + Math.cos(arr2Rad) * circle1Radius)
            setleftpiey(circle1Center.y + Math.sin(arr2Rad) * circle1Radius)
          //这部分是获取左侧大图的2部分数据各占饼图的多少。算角度和坐标点
          
          setStartAngle(chpre)
            setRorate(roratedeg)


            var ctx = canvas.getContext("2d");
            // 获取父元素的宽度
            // 设置canvas宽度和高度与其兄弟元素相同
            const parentWidth = canvas.parentNode.offsetWidth;
            console.log('parentWidth', parentWidth)
            // const parentHeight = canvas.parentNode.offsetHeight-24;
            const parentHeight = 150;
            canvas.width = parentWidth;
            canvas.height = parentHeight;

            console.log(circle2Center, leftpiex, leftpiey)
            ctx.beginPath();
            ctx.moveTo(circle2Center.x, 135); // 将画笔移动到饼图2的边点
            ctx.lineTo(leftpiex, leftpiey); // 画线到饼图2上与饼图1 arr2圆周相对应的点
            ctx.strokeStyle = 'red'; // 设置线条颜色
            ctx.lineWidth = 2; // 设置线条宽度
            ctx.stroke();

            ctx.beginPath();
            ctx.moveTo(circle2Center.x, 15); // 将画笔移动到饼图2的边点
            ctx.lineTo(rightpiex, rightpiey); // 画线到饼图2上与饼图1 arr2圆周相对应的点
            ctx.strokeStyle = 'red'; // 设置线条颜色
            ctx.lineWidth = 2; // 设置线条宽度
            ctx.stroke();







        },
    })

    // 图旋转函数
     const calculatePieChartAngles = (data) => {
        const total = data.reduce((acc, item) => acc + item.value, 0);
        console.log('total', total)
        return data.map((item, index) => {
            const itemPercentage = item.value / total;
            const itemAngle = itemPercentage * 360;
            return { ...item, angle: itemAngle, key: index };
        });
    }

    
    
    //大图和小图的charts设置
    const option1: ECOption = {
        tooltip: {
            trigger: 'item'
        },
        legend: false,
        series: [
            {
                name: '大图',
                type: 'pie',
                radius: '75',
                startAngle: startAngle,
                data: dueOverdue,

                emphasis: {
                    itemStyle: {
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                }
            }
        ]
    };
    const option2: ECOption = {
        tooltip: {
            trigger: 'item'
        },
        legend: false,
        series: [
            {
                name: '小图',
                type: 'pie',
                radius: '60',
                data: delayOverdue,
                emphasis: {
                    itemStyle: {
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                }
            }
        ]
    };
    
    }
    
    export default OverduePie;
    
    
   // 页面部分
   
      <Spin spinning={loadMARKET}>
                            <div className="desktop_overduePie_con" ref={refpie}   >
                                <div style={{ display: 'flex', zIndex: 10 }} id="divpie">
                                    <div className="pieCharts" style={{ width: '50%', position: 'relative', }}>
                                        <ReactEChartsCore
                                            echarts={echarts}
                                            option={option1}
                                            theme={"theme_name"}
                                            style={{ width: "100%", height: "150px" }}
                                        />

                                    </div>
                                    <div className="pieCharts" style={{ width: '50%', }}>
                                        <ReactEChartsCore
                                            echarts={echarts}
                                            option={option2}
                                            theme={"theme_name"}
                                            style={{ width: "100%", height: "150px" }}
                                        />


                                    </div>

                                </div>
                                <canvas ref={canvasRef} id="targetcanvas" style={{ position: 'absolute', top: 0, left: 0, zIndex: 2 }} />;


                            </div>
                            <div style={{ display: 'flex', backgroundColor: '#ff00ff' }}>
                                <div className="title" style={{ textAlign: 'center', width: '50%' }}>
                                    大图部分
                                </div>
                                <div className="title"> </div>
                            </div>
                        </Spin>

参考

以下是使用HTMLCanvas绘制你所描述场景的代码示例:

```html
<!DOCTYPE html>
<html>
<head>
<style>
  canvas {
    border: 1px solid black;
  }
</style>
</head>
<body>

<canvas id="myCanvas" width="400" height="200"></canvas>

<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

// 绘制a圆
var aCenterX = 100;
var aCenterY = canvas.height / 2;
var aRadius = 50;
var aStartAngle = 0;
var aEndAngle = Math.PI * 2 / 3;

ctx.beginPath();
ctx.moveTo(aCenterX, aCenterY);
ctx.arc(aCenterX, aCenterY, aRadius, aStartAngle, aEndAngle, false); // 蓝色扇形
ctx.fillStyle = "blue";
ctx.fill();

ctx.beginPath();
ctx.arc(aCenterX, aCenterY, aRadius, aEndAngle, Math.PI * 2, false); // 红色扇形
ctx.fillStyle = "red";
ctx.fill();

// 绘制b圆
var bCenterX = aCenterX + 200;
var bCenterY = canvas.height / 2;
var bRadius = 50;
var bStartAngle = Math.PI * 2 / 3;
var bEndAngle = Math.PI * 2;

ctx.beginPath();
ctx.moveTo(bCenterX, bCenterY);
ctx.arc(bCenterX, bCenterY, bRadius, bStartAngle, bEndAngle, false); // 蓝色扇形
ctx.fillStyle = "blue";
ctx.fill();

ctx.beginPath();
ctx.arc(bCenterX, bCenterY, bRadius, 0, bStartAngle, false); // 红色扇形
ctx.fillStyle = "red";
ctx.fill();

// 连接线
ctx.beginPath();
ctx.moveTo(aCenterX + Math.cos(aEndAngle) * aRadius, aCenterY + Math.sin(aEndAngle) * aRadius);
ctx.lineTo(bCenterX + Math.cos(bStartAngle) * bRadius, bCenterY + Math.sin(bStartAngle) * bRadius);
ctx.strokeStyle = "red";
ctx.stroke();

ctx.beginPath();
ctx.moveTo(aCenterX + Math.cos(aStartAngle) * aRadius, aCenterY + Math.sin(aStartAngle) * aRadius);
ctx.lineTo(bCenterX + Math.cos(bEndAngle) * bRadius, bCenterY + Math.sin(bEndAngle) * bRadius);
ctx.strokeStyle = "red";
ctx.stroke();
</script>

</body>
</html>

这段代码将在Canvas上绘制出你所描述的两个圆和连接线的图案,圆的半径为50px,且满足要求的颜色和连接线。

参考2
<!--
  @author: yangwenjun
  @Created by yangwenjun on 2023/07/19 21:04:48
  @file: canvas.html
  @description:
  ==================
  Usage:
==================
-->

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas</title>
<style>
  body {
    margin: 0;
  }

  canvas {
    border: 1px solid black;
    width: 50%;
    height: 50%;
  }
</style>
</head>

<body onload="draw()">

<canvas id="target"></canvas>

<script>

  /**
   * 获取切点
   * @param c1 大圆
   * @param c2 小圆
   * @param r1 大圆半径
   * @param r2 小圆半径
   */
  function calcQieDian(c1, c2, r1, r2) {
    //圆心之间的距离
    let d = Math.sqrt(Math.pow(c1.x - c2.x, 2) + Math.pow(c1.y - c2.y, 2));
    //外公切线与连心线夹角的角度
    let theta = Math.acos((r1 - r2) / d);
    let vc1c2 = { x: c2.x - c1.x, y: -c2.y + c1.y }; //屏幕坐标系与笛卡尔坐标系是y轴是反着的
    let radC1C2 = Math.acos(vc1c2.x / Math.sqrt(Math.pow(vc1c2.x, 2) + Math.pow(vc1c2.y, 2)));

    if (c2.y <= c1.y) {
      //大圆上的切点
      let p1 = { x: c1.x + Math.cos(theta + radC1C2) * r1, y: c1.y - Math.sin(theta + radC1C2) * r1 };
      let p2 = { x: c1.x + Math.cos(theta - radC1C2) * r1, y: c1.y + Math.sin(theta - radC1C2) * r1 };
      //小圆上的切点
      let p3 = { x: c2.x + Math.cos(theta + radC1C2) * r2, y: c2.y - Math.sin(theta + radC1C2) * r2 };
      let p4 = { x: c2.x + Math.cos(theta - radC1C2) * r2, y: c2.y + Math.sin(theta - radC1C2) * r2 };
      return { p1: p1, p2: p2, p3: p3, p4: p4 };
    } else {
      radC1C2 = Math.PI - radC1C2;
      //大圆上的切点
      let p1 = { x: c1.x + Math.cos(Math.PI - theta - radC1C2) * r1, y: c1.y + Math.sin(Math.PI - theta - radC1C2) * r1 };
      let p2 = { x: c1.x + Math.cos(Math.PI - (theta - radC1C2)) * r1, y: c1.y - Math.sin(Math.PI - (theta - radC1C2)) * r1 };
      //小圆上的切点
      let p3 = { x: c2.x + Math.cos(Math.PI - theta - radC1C2) * r2, y: c2.y + Math.sin(Math.PI - theta - radC1C2) * r2 };
      let p4 = { x: c2.x + Math.cos(Math.PI - (theta - radC1C2)) * r2, y: c2.y - Math.sin(Math.PI - (theta - radC1C2)) * r2 };
      return { p1: p1, p2: p2, p3: p3, p4: p4 };
    }
  }


  function drawLine(ctx, pointStart, pointEnd) {
    ctx.beginPath();
    ctx.moveTo(pointStart.x, pointStart.y);
    ctx.lineTo(pointEnd.x, pointEnd.y);
    ctx.stroke();
  }

  function draw() {
    var canvas = document.getElementById('target');
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight > 600 ? window.innerHeight : 600

    if (canvas.getContext) {
      var ctx = canvas.getContext("2d");
      // 
      const pointA = { x: 600, y: 200, r: 100 }
      const pointB = { x: 200, y: 260, r: 150 }

      /* arc(x, y, 半经, 开始孤度, 结束孤度, 方向)*/
      ctx.beginPath()
      ctx.arc(
        pointA.x, pointA.y, // 圆心位置
        pointA.r, // 半径
        0, // 起始角度
        Math.PI * 4 / 2 // 结束角度 Math.PI 180deg
      )

      ctx.moveTo(pointA.x, pointA.y,) // 圆A 圆心
      ctx.arc(
        pointA.x, pointA.y, // 圆心位置
        1, // 半径
        0, // 起始角度
        Math.PI * 4 / 2 // 结束角度 Math.PI 180deg
      )

      ctx.moveTo(350, 260)

      ctx.arc(
        pointB.x, pointB.y, // 圆心位置
        pointB.r, // 半径
        0, // 起始角度
        Math.PI * 4 / 2 // 结束角度 Math.PI 180deg
      )

      ctx.moveTo(pointB.x, pointB.y,) // 圆B 圆心
      ctx.arc(
        pointB.x, pointB.y, // 圆心位置
        1, // 半径
        0, // 起始角度
        Math.PI * 4 / 2 // 结束角度 Math.PI 180deg
      )
      ctx.lineWidth = 5 // 线宽
      ctx.stroke() // 线路


      let p = calcQieDian(
        { x: pointA.x, y: pointA.y },
        { x: pointB.x, y: pointB.y },
        pointA.r, pointB.r
      );

      drawLine(ctx, p.p1, p.p3);
      drawLine(ctx, p.p2, p.p4);
    }
  }
</script>
</body>

</html>
```js
参考3 是其他大佬的笔记
https://www.jianshu.com/p/f29f658c432c
https://blog.csdn.net/L25000/article/details/105627815?ydreferer=aHR0cHM6Ly9jbi5iaW5nLmNvbS8%3D

** 手动画图**

解析:

  • 思路搜两个饼图,数据两条,找到最小的角度,初始角度为0,逆时针转最小角度一半,找到 饼图交界处的点,创建数组推入点,根据点画线。
  • 更改角度之后,因为转回去了一半,所以显示还是按照一半一半的来 image.png
<!DOCTYPE html>
<html>

<head>
  <title>Two Non-Overlapping Pie Charts</title>
</head>

<body>
  <canvas id="pieChartCanvas" width="400" height="400"></canvas>

  <script>
    // Get the canvas element and its context
    var canvas = document.getElementById("pieChartCanvas");
    var ctx = canvas.getContext("2d");

    const circlePoints = []


    function drawLine(ctx, pointStart, pointEnd) {
      ctx.beginPath();
      ctx.moveTo(pointStart.x, pointStart.y);
      ctx.lineTo(pointEnd.x, pointEnd.y);
      ctx.stroke();
    }

    // Define data for the two pie charts
    var data1 = [
      { label: "Slice 1", value: 20, color: "#FF5733" },
      { label: "Slice 2", value: 80, color: "#FFC300" }
    ];

    var data2 = [
      { label: "Slice 1", value: 10, color: "#36A2EB" },
      { label: "Slice 2", value: 90, color: "#8E44AD" }
    ];

    // Function to draw a pie chart with given data, center, radius, and rotation
    function drawPieChart(data, centerX, centerY, radius, rotation) {
      var total = data.reduce((sum, slice) => sum + slice.value, 0);
      var minSlice = data.reduce(function (prev, current) {
        return (prev.value < current.value) ? prev : current;
      });
      var minSliceAngle = (minSlice.value / 100) * Math.PI * 2;

      var startAngle = rotation - minSliceAngle / 2;

      for (var i = 0; i < data.length; i++) {
        var sliceAngle = (data[i].value / total) * 2 * Math.PI;

        // Calculate intersection point with the circle at the segment boundary
        var angle = startAngle + sliceAngle;
        var x = centerX + radius * Math.cos(angle);
        var y = centerY + radius * Math.sin(angle);
        circlePoints.push({ x: x, y: y })
        // Draw the slice
        ctx.beginPath();
        ctx.moveTo(centerX, centerY);
        ctx.arc(centerX, centerY, radius, startAngle, startAngle + sliceAngle);
        ctx.closePath();
        ctx.fillStyle = data[i].color;
        ctx.fill();

        // Draw a point at the segment boundary
        ctx.beginPath();
        ctx.arc(x, y, 5, 0, 2 * Math.PI);
        ctx.fillStyle = "#000";
        ctx.fill();

        // Update the starting angle for the next slice
        startAngle += sliceAngle;
      }
    }

    // Draw the two pie charts
    // drawPieChart(data1, canvas.width / 4, canvas.height / 2, 100, -Math.PI / 4);
    // drawPieChart(data2, canvas.width * 3 / 4, canvas.height / 2, 100, -Math.PI / 4 - Math.PI / 2);
    drawPieChart(data1, canvas.width / 4, canvas.height / 2, 50, 0);
    drawPieChart(data2, canvas.width * 3 / 4, canvas.height / 2, 50, 0);
    //

    drawLine(ctx, circlePoints[0], circlePoints[2],)
    drawLine(ctx, circlePoints[1], circlePoints[3],)
  </script>
</body>

</html>