预览

  • Preview | Usage Source | Pie Source | Tutorial
  • Wechart by Cax
  • Cax

众所周知 Cax 既能开发游戏、又能开发图表。本文将从饼图开始 Wechart 的图表之旅。 Wechart 完全基于 Group 体系构建(自定义 Element) ,易维护,可扩展,任何场景可插拔使用。

快速开始

创建饼图实例:

const pie = new Pie([{ name: 'WeChat', value: 10 },{ name: 'Canvas', value: 15 },{ name: 'Cax', value: 23 },{ name: 'Tencent', value: 7 },{ name: 'Wepay', value: 22 }
], {processing: (item) => { return item.value },x: 200,y: 200,r: 160,circleColor: 'white',textOffsetY: -12,font: '20px Arial',color: (index) => {return ['#4BC0C0', '#FF6485', '#FFA07A', '#ADACB9', '#A37AC1'][index]},label: (item) => {return item.name},tooltip: (item) => {return item.name + '<br/>' + item.value}}
)
复制代码

上面各项配置项很清晰明了,不做解释,开发者可自行修改参数看饼图的变化,下面把饼图添加到舞台:

const stage = new cax.Stage(640, 400, 'body')
stage.add(pie)
stage.update()
复制代码

stage 是最大的容器,通过 add 方法往里面加对象,然后 update 舞台就能显示。

显示和隐藏饼图:

pie.show()
pie.hide()
复制代码

实现原理

看到上面的 DEMO 可以会有几方面技术需要讲解:

  • Pie 对象和 Group 的关系
  • Cax 扇形绘制
  • 展开和收缩动画实现
  • 文字和文字走线显示在对应扇形的中间
  • 显示兼容 PC 和 Mobile
  • 交互兼容 PC 和 Mobile
  • 渐变和点击弹出和移除收缩实现
  • Tooltip 实现

Pie 对象和 Group 的关系

先看 cax 内置的 Group 对象, Group 用于分组, group 也可以嵌套 group,父容器的属性会叠加在子属性上, 比如:

  • group 的 x 是 100, group 里的 bitmap 的 x 是 200, 最后 bitmap 渲染到 stage 上的 x 是 300
  • group 的 alpha 是 0.7, group 里的 bitmap 的 alpha 是 0.6, 最后 bitmap 渲染到 stage 上的 alpha 是 0.42
const group = new cax.Group()
const rect = new cax.Rect(100, 100 {fillStyle: 'black'
})
group.add(rect)
stage.add(group)
stage.update()
复制代码

Pie 对象正是自定义 Element,继承自 Group:

class Pie extends Group {constructor (data, option) {super()
复制代码

一般情况下,稍微复杂组合体都建议使用继承自 Group,这样利于扩展也方便管理自身内部的元件。 可以看到小游戏的 DEMO 里的 Player、Bullet、Enemy、Background 全都是继承自 Group。

扇形绘制

Cax 内置 Graphics,可以使用连缀 Canvas API 的方式绘制图形:

const sector = new cax.Graphics()
sector.beginPath().moveTo(0, 0).arc(0, 0, 30, 0, Math.PI/2).closePath().fillStyle('green').fill().strokeStyle('red').lineWidth(2).stroke()stage.add(sector)
复制代码

这里假设你已经创建好了舞台。效果如下:

所以一个饼图就是把圆分成若干个扇形。怎么分? arc 方法传入动态数据:

let current = 0data.forEach((item, index) => {const sector = new cax.Graphics()sector.beginPath().moveTo(0, 0).arc(0, 0, 30, current, current += Math.PI * 2 * item.value / totalValue).closePath().fillStyle('green').fill().strokeStyle('red').lineWidth(2).stroke()
})
复制代码

其中 totalValue 为所有 item.value 的和。可以看到上面是平分一个圆。那么怎么平分一个扇形?能运动平分的角度吗?

展开和收缩动画实现

看这行代码:

.arc(0, 0, 30, current, current += Math.PI * 2 * item.value / totalValue)
复制代码

把 Math.PI * 2 改成 totalAngle 动态变量就可以!

let totalAngle = 0
...
...
.arc(0, 0, 30, current, current += totalAngle * item.value / totalValue)
复制代码

运动 totalAngle 并且进行重绘:

 cax.To.get(option).to({ totalAngle: Math.PI * 2 }, option.duration, option.easing).progress((object) => {current = option.beginsectorGroup.forEach((item, index) => {item.clear().beginPath().moveTo(0, 0).arc(0, 0, r, current, current += object.totalAngle * option.processing(item) / totalValue).closePath().fillStyle(option.color(index)).fill().strokeStyle(option.circleColor).lineWidth(2).stroke().closePath()})}).........
复制代码

使用 cax 内置的 to2to 运动能力。这里需要提醒的是,progress 方法会不断地执行,为了防止 sector 的 graphics path 不断叠加,在循环执行的代码里一定要调用 clear 来清除 graphics 的以前的 Canvas 绘制命令。

文字和文字走线

文字和走线分四种情况:

if (angle >= 0 && angle < Math.PI / 2) {} else if (angle >= Math.PI / 2 && angle < Math.PI) {} else if (angle >= Math.PI && angle < Math.PI + Math.PI / 2) {} else }
复制代码

需要注意的是:

  • 落在左边的文字的 x 坐标需要减去文件的宽度。 Cax 内置的 Text 可以使用 getWidth() 方法获取到文字的宽度
  • 走线的第一根线角度也分两种情况,1、3象限平行,2、4象限平行,走线的第二根先角度都是平行于 y 轴(如上图所示,相同颜色圈中的线是平行的)

显示与交互兼容 PC 和 Mobile

从 javascript 里会发现 canvas 的宽高是 640*400:

const stage = new cax.Stage(640, 400, 'body')
复制代码

就和我们平时使用两倍图一样,在移动端通过 media 把 canvas 变成一半宽度:

 @media screen and (max-width: 500px) {  canvas {width : 320px}
}
复制代码

这个时候会出现一个问题!因为 cax 会把 canvas 上的事件过度给 cax 内置对象,事件发生的坐标因为 canvas 宽高的变化而变化了, 移动端点击事件触发位置不准确了!这个时候需要 scaleEventPoint 方法来校正坐标:

if (window.innerWidth <= 500) {stage.scaleEventPoint(0.5, 0.5)
}
复制代码

搞定!这样不管是在 PC 鼠标还是移动 Mobile 触摸都能精准触发事件。

渐变和点击弹出和移除收缩实现

function fadeIn(obj) {obj.alpha = 0To.get(obj).to({ alpha: 1 }, 600).start()
}function fadeOut(obj) {obj.alpha = 1To.get(obj).to({ alpha: 0 }, 600).start()
}function bounceIn(obj, from, to) {from = from || 0obj.from = fromTo.get(obj).to({ scaleX: to || 1, scaleY: to || 1 }, 300, cax.easing.bounceOut).start()
}function bounceOut(obj, from, to) {from = from || 1obj.from = fromTo.get(obj).to({ scaleX: to || 0, scaleY: to || 0 }, 300, cax.easing.bounceOut).start()
}
复制代码

基于 cax 内置的 to2to 动画引擎封装了四个方法。

Tooltip 实现

sector.hover(function (evt) {bounceIn(sector, 1, 1.1)tooltip.style.left = (evt.pureEvent.pageX + 5) + 'px'tooltip.style.top = (evt.pureEvent.pageY + 5) + 'px'tooltip.innerHTML = option.tooltip(data[index])tooltip.style.display = 'block'
}, function (evt) {bounceOut(sector, 1.1, 1)tooltip.style.display = 'none'
}, function (evt) {tooltip.style.left = (evt.pureEvent.pageX + 5) + 'px'tooltip.style.top = (evt.pureEvent.pageY + 5) + 'px'
})
复制代码

Cax 内置对象拥有 hover(over, out, move) 方法来监听鼠标或者手指 over、out 和 move。

Tooltip 也是完全基于 DOM 来实现的,这样可以浮在 Canvas 外面,而不会限制在 Canvas 里面。

谁在使用?

Cax 和 Wechart 微信交流群

License

MIT

Cax 渲染的精致响应式饼图相关推荐

  1. vue2的动画,混入Mixin,插件,指令,渲染函数,响应式,MVVM

    文章目录 过渡 & 动画 Transition 组件 基于 CSS 的过渡效果 CSS 过渡类名 class 为过渡效果命名 CSS 过渡 transition 实例1: 实例2: CSS 动 ...

  2. matlabeig函数根据什么原理_vue3.0 源码解析二 :响应式原理(下)

    一 回顾上文 上节我们讲了数据绑定proxy原理,vue3.0用到的基本的拦截器,以及reactive入口等等.调用reactive建立响应式,首先通过判断数据类型来确定使用的hander,然后创建p ...

  3. 《响应式网页设计》系列分享专栏

    2019独角兽企业重金招聘Python工程师标准>>> <响应式网页设计>已整理成PDF文档,点击可直接下载至本地查阅 https://www.webfalse.com/ ...

  4. Airbnb开源框架,真响应式架构——MvRx

    今日科技快讯 2月21日凌晨,三星美国旧金山举行Galaxy Unpacked 2019新品发布会.正式发布年度旗舰Galaxy S10系列手机以及折叠手机Galaxy Fold,还推出了首款5G手机 ...

  5. React实例练习-响应式设计、数据绑定、列表渲染、删除单项

    服务菜单 最好的学习就是在实战中成长,做一个<小姐姐服务菜单>应用,练习前面的知识和学习新知识 新建小姐姐组件 先在SRC的目录下面,新建一个文件Xiaojiejie.js 然后写一个基本 ...

  6. MVVM 和 VUE三要素:响应式、模板引擎、渲染

    本文将详细解答以下问题 如何理解mvvm 说一下使用jQuery和使用mvvm框架的区别 说一下对mvvm的理解 vue如何实现响应式 vue如何解析模板 vue的整个实现流程 jQuery和vue的 ...

  7. CSS-0816盒模型 标准盒模型怪异盒模型及其应用背景属性补充小图标使用图标网站可变化单位meta元信息浏览器内核(渲染机制)响应式页面 媒体类型媒体特性opacity和背景色设置透明的区别

    title: "CSS 0816" date: 2022-08-16T11:18:25+08:00 文章目录 title: "CSS 0816" date: 2 ...

  8. eCharts好看的 响应式 圆环饼图 及文字 附vue源码代码

    先看一下echarts图表效果 图表只要resize就会随着页面比例的变化而变化,但是图表中的标识字不可以哦,官方api不接受rem,vh,vw来调整字体大小. 有两种解决办法,第一种是监听页面元素, ...

  9. 《响应式Web设计性能优化》一2.3 Web运行时性能

    本节书摘来异步社区<响应式Web设计性能优化>一书中的第2章,第2.3节,作者: [美]Tom Barker 译者: 余绍亮 , 丁一 , 叶磊 责编: 赵轩,更多章节内容可以访问云栖社区 ...

  10. 判断两个图片的特征向量_响应式布局提高篇 图片正确的打开方式

    作者 | Brilliant Open Web团队 编辑 | Aaron 本文承接上一章的内容,接着介绍响应式布局设计,主要讲如何实现响应式图片.通过对图片适配问题的说明,加深对响应式图片的理解,并分 ...

最新文章

  1. php待办事项设计,如何为待办事项列表应用程序设计ViewModel?
  2. python基础代码-python基础,python基础代码大全
  3. 专家系统中的推理机比较
  4. 基础教程推荐:跟微软大咖学BI
  5. LB服务,软LB的服务能力(下)
  6. C和指针 第十四章 习题
  7. java byte转十六进制_Python 十六进制hexbytesstr之间的转换和Bcc码的生成
  8. 怒肝3W字Java学习路线!从入门到封神全包了(建议收藏)
  9. 关于python里面xlwt操作excel文件的时候去掉页眉页脚
  10. xp计算机描述不能修改,如果WinXP无法更改密码怎么办?该怎么解决?
  11. ChunJunOceanBase联合方案首次发布:构建一体化数据集成方案
  12. leetcode每日一题—781.森林中的兔子
  13. Chrome安装插件SwitchyOmega
  14. 分享 | 物体检测和数据集
  15. C语言 epoll 工作模式之lt 等级触发 level trigger
  16. C语言 随机数实现猜拳游戏
  17. Java从入门到精通十七(Stream 流)
  18. SAP CO01(创建生产订单)/MIGO(发货投料)前台操作
  19. 【疫情动态条形图】用Python开发全球疫情排名动态条形图bar_chart_race
  20. 图文详述:下载安装JDK,搭建Java开发环境,并运行第一个Java程序

热门文章

  1. Charles进行弱网测试
  2. CMPP3.0协议(移动)
  3. 步进电机基础(6.4)-步进电机的特性测量方法-暂态(阻尼)特性的测量和噪音和振动的测量
  4. 西铁城手表最外圈数字是什么_有的手表表盘外面有一圈数字,可以转动,是计算什么用的?...
  5. 随机梯度下降SGD算法理解
  6. 内点法外点法matlab代码,分享:惩罚函数法(内点法、外点法)求解约束优化问题最优值...
  7. 罚函数——内点罚函数算法
  8. Value-Decomposition Networks For Cooperative Multi-Agent Learning(VDN)
  9. 微信小程序之蓝牙打印
  10. mysql软件可行性分析报告_软件工程作业 图书馆管理系统可行性分析报告