highcharts实现旭日图外部label

设计稿

        设计稿如上图,有看到同事用多个饼图嵌套实现旭日图的例子,初步感觉该方法在数据变换的时候需要去调整饼图的角度,后端返回的数据是变化的,感觉不适合。
        highcharts可以设置distance来调整饼图外部牵引线的长度,文档写明只适用于饼图。感觉旭日图的label信息不能显示在图形外部。
        打算用svg来绘制牵引线和label的内容,需要先拿到与之相关的坐标点。Load函数中this.series[0].data包含每个图形的信息,graphic有图形绘制的信息,打算以图形的中心点起点绘制牵引线。先试着为图形添加线条:

        发现没有加上,应该不是用这种方式更新SVG图形,找了很久,发现SVG的元素要用createElementNS来创建:

代码
效果

        先找出图形起点线的中点:

代码
效果

        要得到图形的中点位置,感觉通过图形弧度的一半和起始线中心点就可以得到:

代码
效果

        尝试调整sx和sy的正负值,发现总有中点位置是错的。尝试用图形的起始弧度和图形中心点弧度不同区域调整sx和sy的值,一开始是0°到90°,90°到180°,180°到270°,270°到360°,后面发现可以越分越细,越分越细,感觉可能可以细到一度。
        Math.sin和Math.cos的计算是自带正负值的,感觉可以加上它们的结果而不用调整结果的正负值。
        重新计算起始线的中心点,以圆心点位置偏移,不以图形的起始点作为偏移点:

        发现绘制的点都落在对应图形的起始线中心上,可以不用纠结不同区间做不同的加减法,根据以上逻辑计算图形的中心点:

代码
效果

        发现绘制的点都落在对应图形的中心上了。对于牵引线的第一条线,打算从内往外的第一层的图形的线长是3 * radius,第二层是2 * radius,第三次是radius,根据这种设想计算第一条线的另一个点:

代码
效果

        第二条线是一条水平线,根据图形中心点对应的位置的左右位置往左右方向绘制:

代码
效果

        第二条线的绘制看起没有问题,就是添加上去的svg将旭日图割开的样式,添加设置path.setAttribute('fill', ‘none’)就可以了。
        接下来添加文本,看了svg的text,有人说做不到分行,先处理一下文本的分行:

        将每一行加到tspan,再将tspan添加到text中:

代码
效果

        现在需要加蔬菜模块的往外移动,highcharts旭日图有sliced属性用来设置,将sliced设置为true:

        蔬菜模块往外移动后,发现图形的中心点位置发生改变,调整一下:

代码
效果

        15是一个大概值,效果看起来没问题。
        还需要将香蕉的图形半径绘制比其他的大,之前调整highcharts的图形用到graphic.attr,尝试一下:

        发现没有变化,发现graphic还有r属性,该属性对应上每一层图形外圆弧的半径,试着修改一下:

代码
效果

        香蕉图形的中点位置是没有调整大小对应的值,感官上没有问题就这样了。
        调整浏览器页面大小,发现svg添加的内容都对不上了。因为没有在load函数里面使用transform之类,感觉在redraw中不需要先复原,直接再调用一遍load函数里面的执行就好了,结果:

        感觉要么去掉之前添加内容,要么调整之前内容的位置,感觉先删除比调整要快。使用textDoc.className设置class的名称,发现会报错,改用textDoc.classList.add('text-content'):

参考:
svg文本<text>详解:https://blog.csdn.net/lweiyue/article/details/125776515
JavaScript - 动态添加文本到SVG路径:https://www.coder.work/article/7892839

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容