@east-century/crender
v0.0.1
Published
Canvas-based vector graphics rendering plugin
Downloads
4
Maintainers
Readme
CRender是干什么的?
- 它是一个基于canvas的矢量图形渲染插件。
- 它对图形提供动画和鼠标事件支持。
npm安装
$ npm install @east-century/crender
快速体验
<!--资源位于github服务器仅供体验和测试,请勿在生产环境使用-->
<!--调试版-->
<script src="https://github.com/east-century-fex/crender/tree/master/dist/crender.map.js"></script>
<!--压缩版-->
<script src="https://github.com/east-century-fex/crender/tree/master/dist/crender.min.js"></script>
<script>
const { CRender, extendNewGraph } = window.CRender
// do something
</script>
详细文档及示例请移步HomePage.
import CRender from '@east-century/credner'
const canvas = document.getElementById('canvas')
// 实例化 CRender
const render = new CRender(canvas)
// 向render中添加图形
const circle = render.add({ name: 'circle', ... })
类
/**
* @description Class of CRender
* @param {Object} canvas Canvas 节点
* @return {CRender} CRender实例
*/
class CRender {
// ...
}
实例属性
ctx
/**
* @description canvas context
* @type {Object}
* @example ctx = canvas.getContext('2d')
*/
area
/**
* @description canvas宽高
* @type {Array<Number>}
* @example area = [300,100]
*/
animationStatus
/**
* @description render是否处于动画渲染中
* @type {Boolean}
* @example animationStatus = true|false
*/
graphs
/**
* @description 已添加的图形
* @type {Array<Graph>}
* @example graphs = [Graph, Graph, ...]
*/
color
/**
* @description 颜色插件
* @type {Object}
*/
bezierCurve
/**
* @description 贝塞尔曲线插件
* @type {Object}
*/
原型方法
向render中添加图形
克隆一个图形
删除render中的一个图形
删除render中所有的图形
渲染render中所有的图形
擦除canvas绘制区域
使动画队列不为空且animationPause不为false的图形进行动画
add
/**
* @description 向render中添加图形
* @param {Object} config 图形配置
* @return {Graph} 图形实例
*/
CRender.prototype.add = function (config = {}) {
// ...
}
Clone
/**
* @description 克隆一个图形
* @param {Graph} graph 将要被克隆的图形
* @return {Graph} 克隆的图形
*/
CRender.prototype.clone = function (graph) {
}
delGraph
/**
* @description 删除render中的一个图形
* @param {Graph} graph 将要删除的图形实例
* @return {Undefined} 无返回值
*/
CRender.prototype.delGraph = function (graph) {
// ...
}
delAllGraph
/**
* @description 删除render中所有的图形
* @return {Undefined} 无返回值
*/
CRender.prototype.delAllGraph = function () {
// ...
}
drawAllGraph
/**
* @description 渲染render中所有的图形
* @return {Undefined} 无返回值
*/
CRender.prototype.drawAllGraph = function () {
// ...
}
clearArea
/**
* @description 擦除canvas绘制区域
* @return {Undefined} 无返回值
*/
CRender.prototype.clearArea = function () {
// ...
}
launchAnimation
/**
* @description 使动画队列不为空且animationPause不为false的图形进行动画
* @return {Promise} Animation Promise
*/
CRender.prototype.launchAnimation = function () {
// ...
}
实例属性
当添加一个图形时,你可以配置这些属性。
- visible
- shape
- style
- drag
- hover
- index
- animationDelay
- animationFrame
- animationCurve
- animationPause
- hoverRect
- mouseEnter
- mouseOuter
- click
visible
/**
* @description 该图形是否可被渲染
* @type {Boolean}
* @default visible = true
*/
shape
/**
* @description 图形形状数据
* @type {Object}
*/
style
/**
* @description 图形样式数据 (Style实例)
* @type {Style}
*/
drag
/**
* @description 是否启用拖拽功能
* @type {Boolean}
* @default drag = false
*/
hover
/**
* @description 是否启用悬浮检测
* @type {Boolean}
* @default hover = false
*/
index
/**
* @description 图形渲染层级,层级高者优先渲染
* @type {Number}
* @default index = 1
*/
animationDelay
/**
* @description 动画延迟时间(ms)
* @type {Number}
* @default animationDelay = 0
*/
animationFrame
/**
* @description 动画帧数
* @type {Number}
* @default animationFrame = 30
*/
animationCurve
/**
* @description 动画缓动曲线
* @type {String}
* @default animationCurve = 'linear'
*/
animationPause
/**
* @description 是否暂停图形动画
* @type {Boolean}
* @default animationPause = false
*/
hoverRect
/**
* @description 矩形悬浮检测盒,配置该项则优先使用其进行鼠标悬浮检测
* @type {Null|Array<Number>}
* @default hoverRect = null
* @example hoverRect = [0, 0, 100, 100] // [矩形起始点 x, y 坐标, 矩形宽, 高]
*/
mouseEnter
/**
* @description 鼠标进入图形事件处理器
* @type {Null|Function}
* @default mouseEnter = null
*/
mouseOuter
/**
* @description 鼠标移出图形事件处理器
* @type {Null|Function}
* @default mouseOuter = null
*/
click
/**
* @description 鼠标点击图形事件处理器
* @type {Null|Function}
* @default click = null
*/
Tip
启用图形的mouseEnter,mouseOuter,click等事件支持需要将hover
属性配置为true
。扩展的新图形需要配置hoverCheck方法以提供事件支持。
原型方法
更新图形状态
更新图形状态(伴随动画)
跳至最后一帧动画
暂停动画行为
尝试动画行为
attr
/**
* @description 更新图形状态
* @param {String} attrName 要更新的属性名
* @param {Any} change 更新的值
* @return {Undefined} 无返回值
*/
Graph.prototype.attr = function (attrName, change = undefined) {
// ...
}
animation
/**
* @description 更新图形状态(伴随动画),仅支持shape和style属性
* @param {String} attrName 要更新的属性名
* @param {Any} change 更新的值
* @param {Boolean} wait 是否存储动画队列,等待下次动画请求
* @return {Promise} Animation Promise
*/
Graph.prototype.animation = async function (attrName, change, wait = false) {
// ...
}
animationEnd
/**
* @description 跳至最后一帧动画
* @return {Undefined} 无返回值
*/
Graph.prototype.animationEnd = function () {
// ...
}
pauseAnimation
/**
* @description 暂停动画行为
* @return {Undefined} 无返回值
*/
Graph.prototype.pauseAnimation = function () {
// ...
}
playAnimation
/**
* @description 尝试动画行为
* @return {Undefined} 无返回值
*/
Graph.prototype.playAnimation = function () {
// ...
}
生命周期
当向render中添加图形时,你可以配置如下几个方法,它们将在特定时刻被调用。
图形添加时被调用
图形绘制前被调用
图形绘制后被调用
图形移动前被调用
图形移动后被调用
图形删除前被调用
图形删除后被调用
added
/**
* @description 图形添加时被调用
* @param {Graph} 图形实例
*/
config = {
//...,
added ({ shape, style }) {
// 一些操作...
}
}
beforeDraw
/**
* @description 图形绘制前被调用,图形样式已经初始化完毕
* 你可以在此时修改ctx属性
* @param {Graph} 图形实例
* @param {CRender} CRender实例
*/
config = {
//...,
beforeDraw ({ shape, style }, { ctx }) {
// 一些操作...
ctx.stroke = 'transparent'
}
}
drawed
/**
* @description 图形绘制后被调用
* @param {Graph} 图形实例
* @param {CRender} CRender实例
*/
config = {
//...,
drawed ({ shape, style }, { ctx }) {
// 一些操作...
}
}
beforeMove
/**
* @description 图形移动前被调用,移动行为发生前
* @param {Event} 鼠标事件
* @param {Graph} 图形实例
*/
config = {
//...,
beforeMove ({ offsetX, offsetY }, { shape, style }) {
// 一些操作...
}
}
moved
/**
* @description 图形移动后被调用,移动行为发生后
* @param {Event} 鼠标事件
* @param {Graph} 图形实例
*/
config = {
//...,
moved ({ offsetX, offsetY }, { shape, style }) {
// 一些操作...
}
}
beforeDelete
/**
* @description 图形删除前被调用
* @param {Graph} 图形实例
*/
config = {
//...,
beforeDelete ({ shape, style }) {
// 一些操作...
}
}
deleted
/**
* @description 图形删除后被调用
* @param {Graph} 图形实例
*/
config = {
//...,
deleted ({ shape, style }) {
// 一些操作...
}
}
实例属性
- fill
- stroke
- opacity
- lineCap
- lineJoin
- lineDash
- lineDashOffset
- shadowBlur
- shadowColor
- shadowOffsetX
- shadowOffsetY
- lineWidth
- graphCenter
- scale
- rotate
- translate
- hoverCursor
- fontStyle
- fontVarient
- fontWeight
- fontSize
- fontFamily
- textAlign
- textBaseline
- gradientColor
- gradientType
- gradientParams
- gradientWith
- gradientStops
- colors
fill
/**
* @description 图形填充颜色的Rgba值
* @type {Array<Number>}
* @default fill = [0, 0, 0, 1]
*/
stroke
/**
* @description 图形描边颜色的Rgba值
* @type {Array<Number>}
* @default stroke = [0, 0, 0, 1]
*/
opacity
/**
* @description 图形透明度
* @type {Number}
* @default opacity = 1
*/
lineCap
/**
* @description Ctx的lineCap属性值
* @type {Null|String}
* @default lineCap = null
* @example lineCap = 'butt'|'round'|'square'
*/
lineJoin
/**
* @description Ctx的lineJoin属性值
* @type {Null|String}
* @default lineJoin = null
* @example lineJoin = 'round'|'bevel'|'miter'
*/
lineDash
/**
* @description Ctx的lineDash属性值
* @type {Null|Array<Number>}
* @default lineDash = null
* @example lineDash = [10, 10]
*/
lineDashOffset
/**
* @description Ctx的lineDashOffset属性值
* @type {Null|Number}
* @default lineDashOffset = null
* @example lineDashOffset = 10
*/
shadowBlur
/**
* @description Ctx的shadowBlur属性值
* @type {Number}
* @default shadowBlur = 0
*/
shadowColor
/**
* @description 图形阴影颜色的Rgba值
* @type {Array<Number>}
* @default shadowColor = [0, 0, 0, 0]
*/
shadowOffsetX
/**
* @description Ctx的shadowOffsetX属性值
* @type {Number}
* @default shadowOffsetX = 0
*/
shadowOffsetY
/**
* @description Ctx的shadowOffsetY属性值
* @type {Number}
* @default shadowOffsetY = 0
*/
lineWidth
/**
* @description Ctx的lineWidth属性值
* @type {Number}
* @default lineWidth = 0
*/
graphCenter
/**
* @description 图形中心点
* @type {Null|Array<Number>}
* @default graphCenter = null
* @example graphCenter = [10, 10]
*/
scale
/**
* @description 图形缩放倍数
* @type {Null|Array<Number>}
* @default scale = null
* @example scale = [1.5, 1.5]
*/
rotate
/**
* @description 图形旋转角度
* @type {Null|Number}
* @default rotate = null
* @example rotate = 10
*/
translate
/**
* @description 图形位移距离
* @type {Null|Array<Number>}
* @default translate = null
* @example translate = [10, 10]
*/
hoverCursor
/**
* @description 鼠标悬浮在图形上时cursor的值
* @type {String}
* @default hoverCursor = 'pointer'
* @example hoverCursor = 'default'|'pointer'|'auto'|'crosshair'|'move'|'wait'|...
*/
fontStyle
/**
* @description Ctx的fontStyle属性值
* @type {String}
* @default fontStyle = 'normal'
* @example fontStyle = 'normal'|'italic'|'oblique'
*/
fontVarient
/**
* @description Ctx的fontVarient属性值
* @type {String}
* @default fontVarient = 'normal'
* @example fontVarient = 'normal'|'small-caps'
*/
fontWeight
/**
* @description Ctx的fontWeight属性值
* @type {String|Number}
* @default fontWeight = 'normal'
* @example fontWeight = 'normal'|'bold'|'bolder'|'lighter'|Number
*/
fontSize
/**
* @description Ctx的fontSize属性值
* @type {Number}
* @default fontSize = 10
*/
fontFamily
/**
* @description Ctx的fontFamily属性值
* @type {String}
* @default fontFamily = 'Arial'
*/
textAlign
/**
* @description Ctx的textAlign属性值
* @type {String}
* @default textAlign = 'center'
* @example textAlign = 'start'|'end'|'left'|'right'|'center'
*/
textBaseline
/**
* @description Ctx的textBaseline属性值
* @type {String}
* @default textBaseline = 'middle'
* @example textBaseline = 'top'|'bottom'|'middle'|'alphabetic'|'hanging'
*/
gradientColor
/**
* @description 用于创建渐变色的颜色
* @type {Null|Array<String>}
* @default gradientColor = null
* @example gradientColor = ['#000', '#111', '#222']
*/
gradientType
/**
* @description 渐变类型
* @type {String}
* @default gradientType = 'linear'
* @example gradientType = 'linear' | 'radial'
*/
gradientParams
/**
* @description 渐变参数
* @type {Array<Number>}
* @default gradientParams = null
* @example gradientParams = [x0, y0, x1, y1] (线性渐变)
* @example gradientParams = [x0, y0, r0, x1, y1, r1] (径向渐变)
*/
gradientWith
/**
* @description 使用渐变色的属性
* @type {String}
* @default gradientWith = 'stroke'
* @example gradientWith = 'stroke' | 'fill'
*/
gradientStops
/**
* @description 渐变色位置
* @type {String|Array<Number>}
* @default gradientStops = 'auto'
* @example gradientStops = 'auto' | [0, .2, .3, 1]
*/
colors
/**
* @description 支持动画过渡的颜色容器
* @type {Array<String>|Object}
* @default colors = null
* @example colors = ['#000', '#111', '#222']
* @example colors = { a: '#000', b: '#111' }
*/
Tip
gradientColor
和gradientParams
被配置后将自动启用渐变。
原型方法
获取图形当前样式配置
getStyle
/**
* @description 获取图形当前样式配置
* @return {Object} 样式配置
*/
Style.prototype.getStyle = function () {
}
CRender提供如下基础矢量图形。
圆形
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| rx | Number
| 0
| 圆心x轴坐标 |
| ry | Number
| 0
| 圆心y轴坐标 |
| r | Number
| 0
| 圆半径 |
const { area: [w, h] } = render
const circleConfig = {
name: 'circle',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
rx: w / 2,
ry: h / 2,
r: 50
},
style: {
fill: '#9ce5f4',
shadowBlur: 0,
shadowColor: '#66eece',
hoverCursor: 'pointer'
},
mouseEnter (e) {
this.animation('shape', { r: 70 }, true)
this.animation('style', { shadowBlur: 20 })
},
mouseOuter (e) {
this.animation('shape', { r: 50 }, true)
this.animation('style', { shadowBlur: 0 })
}
}
const circle = render.add(circleConfig)
椭圆形
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| rx | Number
| 0
| 圆心x轴坐标 |
| ry | Number
| 0
| 圆心y轴坐标 |
| hr | Number
| 0
| 横轴半径 |
| vr | Number
| 0
| 竖轴半径 |
const { area: [w, h] } = render
const ellipseConfig = {
name: 'ellipse',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
rx: w / 2,
ry: h / 2,
hr: 80,
vr: 30
},
style: {
fill: '#9ce5f4',
shadowBlur: 0,
shadowColor: '#66eece',
scale: [1, 1],
hoverCursor: 'pointer'
},
mouseEnter (e) {
this.animation('style', { scale: [1.5, 1.5], shadowBlur: 20 })
},
mouseOuter (e) {
this.animation('style', { scale: [1, 1], shadowBlur: 0 })
}
}
const ellipse = render.add(ellipseConfig)
矩形
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| x | Number
| 0
| 矩形左上角x轴坐标 |
| y | Number
| 0
| 矩形左上角y轴坐标 |
| w | Number
| 0
| 矩形宽度 |
| h | Number
| 0
| 矩形高度 |
const { area: [w, h] } = render
const rectConfig = {
name: 'rect',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
x: w / 2 - rectWidth / 2,
y: h / 2 - rectHeight / 2,
w: rectWidth,
h: rectHeight
},
style: {
fill: '#9ce5f4',
shadowBlur: 0,
shadowColor: '#66eece',
hoverCursor: 'pointer',
translate: [0, 0]
},
mouseEnter (e) {
this.animation('shape', { w: 400 }, true)
this.animation('style', { shadowBlur: 20, translate: [-100, 0] })
},
mouseOuter (e) {
this.animation('shape', { w: 200 }, true)
this.animation('style', { shadowBlur: 0, translate: [0, 0] })
}
}
const rect = render.add(rectConfig)
环形
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| rx | Number
| 0
| 中心点x轴坐标 |
| ry | Number
| 0
| 中心点y轴坐标 |
| r | Number
| 0
| 环半径 |
const { area: [w, h] } = render
const ringConfig = {
name: 'ring',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
rx: w / 2,
ry: h / 2,
r: 50
},
style: {
stroke: '#9ce5f4',
lineWidth: 20,
hoverCursor: 'pointer',
shadowBlur: 0,
shadowColor: '#66eece'
},
mouseEnter (e) {
this.animation('style', { shadowBlur: 20, lineWidth: 30 })
},
mouseOuter (e) {
this.animation('style', { shadowBlur: 0, lineWidth: 20 })
}
}
const ring = render.add(ringConfig)
弧形
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| rx | Number
| 0
| 中心点x轴坐标 |
| ry | Number
| 0
| 中心点y轴坐标 |
| r | Number
| 0
| 弧半径 |
| startAngle | Number
| 0
| 弧起始弧度值 |
| endAngle | Number
| 0
| 弧结束弧度值 |
| clockWise | Boolean
| true
| 是否顺时针 |
const { area: [w, h] } = render
const arcConfig = {
name: 'arc',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
rx: w / 2,
ry: h / 2,
r: 60,
startAngle: 0,
endAngle: Math.PI / 3
},
style: {
stroke: '#9ce5f4',
lineWidth: 20,
shadowBlur: 0,
rotate: 0,
shadowColor: '#66eece',
hoverCursor: 'pointer'
},
mouseEnter (e) {
this.animation('shape', { endAngle: Math.PI }, true)
this.animation('style', { shadowBlur: 20, rotate: -30, lineWidth: 30 })
},
mouseOuter (e) {
this.animation('shape', { endAngle: Math.PI / 3 }, true)
this.animation('style', { shadowBlur: 0, rotate: 0, lineWidth: 20 })
}
}
const arc = render.add(arcConfig)
扇形
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| rx | Number
| 0
| 中心点x轴坐标 |
| ry | Number
| 0
| 中心点y轴坐标 |
| r | Number
| 0
| 扇形半径 |
| startAngle | Number
| 0
| 扇形起始弧度值 |
| endAngle | Number
| 0
| 扇形结束弧度值 |
| clockWise | Boolean
| true
| 是否顺时针 |
const { area: [w, h] } = render
const sectorConfig = {
name: 'sector',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
rx: w / 2,
ry: h / 2,
r: 60,
startAngle: 0,
endAngle: Math.PI / 3
},
style: {
fill: '#9ce5f4',
shadowBlur: 0,
rotate: 0,
shadowColor: '#66eece',
hoverCursor: 'pointer'
},
mouseEnter (e) {
this.animation('shape', { endAngle: Math.PI, r: 70 }, true)
this.animation('style', { shadowBlur: 20, rotate: -30, lineWidth: 30 })
},
mouseOuter (e) {
this.animation('shape', { endAngle: Math.PI / 3, r: 60 }, true)
this.animation('style', { shadowBlur: 0, rotate: 0, lineWidth: 20 })
}
}
const sector = render.add(sectorConfig)
正多边形
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| rx | Number
| 0
| 中心点x轴坐标 |
| ry | Number
| 0
| 中心点y轴坐标 |
| r | Number
| 0
| 外接圆半径 |
| side | Number
| 0
| 边数 |
const { area: [w, h] } = render
const regPolygonConfig = {
name: 'regPolygon',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
rx: w / 2,
ry: h / 2,
r: 60,
side: 6
},
style: {
fill: '#9ce5f4',
hoverCursor: 'pointer',
shadowBlur: 0,
rotate: 0,
shadowColor: '#66eece'
},
mouseEnter (e) {
this.animation('shape', { endAngle: Math.PI, r: 100 }, true)
this.animation('style', { shadowBlur: 20, rotate: 180 })
},
mouseOuter (e) {
this.animation('shape', { endAngle: Math.PI / 3, r: 60 }, true)
this.animation('style', { shadowBlur: 0, rotate: 0 })
}
}
const regPolygon = render.add(regPolygonConfig)
折线
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| points | Array
| []
| 构成折线的点 |
| close | Boolean
| false
| 是否闭合折线 |
const { area: [w, h] } = render
const top = h / 3
const bottom = h / 3 * 2
const gap = w / 10
const beginX = w / 2 - gap * 2
const points = new Array(5).fill('').map((t, i) =>
[beginX + gap * i, i % 2 === 0 ? top : bottom])
const polylineConfig = {
name: 'polyline',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
points
},
style: {
stroke: '#9ce5f4',
shadowBlur: 0,
lineWidth: 10,
shadowColor: '#66eece',
hoverCursor: 'pointer'
},
mouseEnter (e) {
this.animation('style', { lineWidth: 20, shadowBlur: 20 })
},
mouseOuter (e) {
this.animation('style', { lineWidth: 10, shadowBlur: 0 })
}
}
const polyline = render.add(polylineConfig)
折线(闭合)
const { area: [w, h] } = render
const top = h / 3
const bottom = h / 3 * 2
const gap = w / 10
const beginX = w / 2 - gap * 2
const points = new Array(5).fill('').map((t, i) =>
[beginX + gap * i, i % 2 === 0 ? top : bottom])
points[2][1] += top * 1.3
const polylineClosedConfig = {
name: 'polyline',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
points,
close: true
},
style: {
fill: '#9ce5f4',
shadowBlur: 0,
lineWidth: 10,
shadowColor: '#66eece',
hoverCursor: 'pointer'
},
mouseEnter (e) {
this.animation('style', { shadowBlur: 20 }, true)
const pointsCloned = deepClone(this.shape.points)
pointsCloned[2][1] += top * 0.3
this.animation('shape', { points: pointsCloned })
},
mouseOuter (e) {
this.animation('style', { shadowBlur: 0 }, true)
const pointsCloned = deepClone(this.shape.points)
pointsCloned[2][1] -= top * 0.3
this.animation('shape', { points: pointsCloned })
}
}
const polylineClosed = render.add(polylineClosedConfig)
光滑曲线
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| points | Array
| []
| 构成光滑曲线的点 |
| close | Boolean
| false
| 是否闭合光滑曲线 |
const { area: [w, h] } = render
const top = h / 3
const bottom = h / 3 * 2
const gap = w / 10
const beginX = w / 2 - gap * 2
const points = new Array(5).fill('').map((t, i) =>
[beginX + gap * i, i % 2 === 0 ? top : bottom])
const smoothlineConfig = {
name: 'smoothline',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
points
},
style: {
stroke: '#9ce5f4',
shadowBlur: 0,
lineWidth: 10,
shadowColor: '#66eece',
hoverCursor: 'pointer'
},
mouseEnter (e) {
this.animation('style', { lineWidth: 20, shadowBlur: 20 })
},
mouseOuter (e) {
this.animation('style', { lineWidth: 10, shadowBlur: 0 })
}
}
const smoothline = render.add(smoothlineConfig)
光滑曲线(闭合)
import { getCircleRadianPoint } from '../../CRender/lib/util'
function getPoints (radius, centerPoint, pointNum) {
const PIDived = Math.PI * 2 / pointNum
const points = new Array(pointNum).fill('')
.map((foo, i) =>
getCircleRadianPoint(...centerPoint, radius, PIDived * i)
)
return points
}
const { area: [w, h] } = render
const radius = h / 3
const centerPoint = [w / 2, h / 2]
const smoothlineClosedConfig = {
name: 'smoothline',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
points: getPoints(radius, centerPoint, 3),
close: true
},
style: {
fill: '#9ce5f4',
shadowBlur: 0,
lineWidth: 10,
shadowColor: '#66eece',
hoverCursor: 'pointer'
},
mouseEnter (e) {
this.animation('style', { lineWidth: 20, shadowBlur: 20, rotate: 120 })
},
mouseOuter (e) {
this.animation('style', { lineWidth: 10, shadowBlur: 0, rotate: 0 })
},
setGraphCenter (e, { style }) {
if (e) {
const { movementX, movementY } = e
const [cx, cy] = style.graphCenter
style.graphCenter = [cx + movementX, cy + movementY]
} else {
style.graphCenter = [...centerPoint]
}
}
}
const smoothlineClosed = render.add(smoothlineClosedConfig)
贝塞尔曲线
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| points | Array
| []
| 构成贝塞尔曲线的点 |
| close | Boolean
| false
| 是否闭合贝塞尔曲线 |
const { area: [w, h] } = render
const offsetX = w / 2
const offsetY = h / 2
const points = [
// 起始点
[-100 + offsetX, -50 + offsetY],
// 多段贝塞尔曲线
[
// 控制点1,控制点2,结束点
[0 + offsetX, -50 + offsetY],
[0 + offsetX, 50 + offsetY],
[100 + offsetX, 50 + offsetY]
],
// [...],[...]
]
const bezierCurveConfig = {
name: 'bezierCurve',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
points
},
style: {
lineWidth: 10,
stroke: '#9ce5f4',
shadowBlur: 0,
shadowColor: '#66eece',
hoverCursor: 'pointer'
},
mouseEnter (e) {
this.animation('style', { lineWidth: 20, shadowBlur: 20 })
},
mouseOuter (e) {
this.animation('style', { lineWidth: 10, shadowBlur: 0 })
}
}
const bezierCurve = render.add(bezierCurveConfig)
贝塞尔曲线(闭合)
import { getCircleRadianPoint } from '../../CRender/lib/util'
function getPetalPoints (insideRadius, outsideRadius, petalNum, petalCenter) {
const PI2Dived = Math.PI * 2 / (petalNum * 3)
let points = new Array(petalNum * 3).fill('')
.map((foo, i) =>
getCircleRadianPoint(...petalCenter,
i % 3 === 0 ? insideRadius : outsideRadius,
PI2Dived * i)
)
const startPoint = points.shift()
points.push(startPoint)
points = new Array(petalNum).fill('')
.map(foo => points.splice(0, 3))
points.unshift(startPoint)
return points
}
const { area: [w, h] } = render
const petalCenter = [w / 2, h / 2]
const [raidus1, raidus2, raidus3, raidus4] = [h / 6, h / 2.5, h / 3, h / 2]
const bezierCurveClosedConfig = {
name: 'bezierCurve',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
shape: {
points: getPetalPoints(raidus1, raidus2, 6, petalCenter),
close: true
},
style: {
fill: '#9ce5f4',
shadowBlur: 0,
shadowColor: '#66eece',
hoverCursor: 'pointer'
},
mouseEnter (e, { style: { graphCenter } }) {
this.animation('style', { lineWidth: 20, shadowBlur: 20 }, true)
this.animation('shape', { points: getPetalPoints(raidus3, raidus4, 6, graphCenter) })
},
mouseOuter (e, { style: { graphCenter } }) {
this.animation('style', { lineWidth: 10, shadowBlur: 0 }, true)
this.animation('shape', { points: getPetalPoints(raidus1, raidus2, 6, graphCenter) })
},
setGraphCenter (e, { style }) {
if (e) {
const { movementX, movementY } = e
const [cx, cy] = style.graphCenter
style.graphCenter = [cx + movementX, cy + movementY]
} else {
style.graphCenter = [...petalCenter]
}
}
}
const bezierCurveClosed = render.add(bezierCurveClosedConfig)
文本
shape属性
| 属性名 | 类型 | 默认值 | 注解 |
| :---: | :---: | :---: | :---: |
| content | String
| ''
| 文本内容 |
| position | Array
| [0, 0]
| 文本起始位置 |
| maxWidth | Number
| Undefined
| 文本最大宽度 |
| rowGap | Number
| 0
| 行间距 |
const { area: [w, h] } = render
const centerPoint = [w / 2, h / 2]
const hoverRect = [w / 2 - 100, h / 2 - 30 ,200, 60]
const textConfig = {
name: 'text',
animationCurve: 'easeOutBack',
hover: true,
drag: true,
hoverRect,
shape: {
content: 'CRender',
position: centerPoint,
maxWidth: 200
},
style: {
fill: '#9ce5f4',
fontSize: 50,
shadowBlur: 0,
rotate: 0,
shadowColor: '#66eece',
hoverCursor: 'pointer',
scale: [1, 1],
rotate: 0
},
mouseEnter (e) {
this.animation('style', { shadowBlur: 20, scale: [1.5, 1.5], rotate: 30 })
},
mouseOuter (e) {
this.animation('style', { shadowBlur: 0, scale: [1, 1], rotate: 0 })
},
moved (e, { hoverRect }) {
const { movementX, movementY } = e
hoverRect[0] += movementX
hoverRect[1] += movementY
}
}
const text = render.add(textConfig)
Tip
图形text的鼠标事件依赖
hoverRect
属性,如需鼠标事件生效请对其配置文本中插入
\n
可以进行换行。
CRender提供了一个方法去扩展新的图形,你可以自定义想要的图形。
import { extendNewGraph } from '@east-century/crender'
const graphName = 'newGraph'
const graphConfig = {
shape: { ... },
// ...
}
extendNewGraph(graphName, graphConfig)
extendNewGraph
/**
* @description 扩展新图形
* @param {String} name 图形名称
* @param {Object} config 图形配置
* @return {Undefined} 无返回值
*/
function extendNewGraph (name, config) {
// ...
}
图形配置属性
shape (必须)
/**
* @type {Object}
* @description 图形形状数据
*/
config = {
// ...,
shape: {
// 一些属性...
}
}
validator (必须)
/**
* @type {Function}
* @description 图形添加时将被调用,用于检测图形配置是否合法,
* 若返回值为false则终止添加行为
* @param {Graph} 当前图形实例
* @return {Boolean} 配置是否合法
*/
config = {
// ...,
validator ({ shape }) {
// 检查图形配置...
// return true | false
}
}
draw (必须)
/**
* @type {Function}
* @description 图形绘制器
* @param {CRender} 当前CRender实例
* @param {Graph} 当前图形实例
* @return {Undefined} 无返回值
*/
config = {
// ...,
draw ({ ctx }, { shape }) {
// 绘制...
}
}
hoverCheck (可选)
/**
* @type {Function}
* @description 通过鼠标位置去判断当前图形是否处于鼠标悬浮状态,
* 用于给mouseEnter, mouseOuter, drag, click事件提供支持。
* @param {Array<Number>} 鼠标位置
* @param {Graph} 当前图形实例
* @return {Boolean} 是否处于鼠标悬浮状态
*/
config = {
// ...,
validator ([offsetX, offsetY], { shape }) {
// 检测是否处于鼠标悬浮状态...
// return true | false
}
}
setGraphCenter (可选)
/**
* @type {Function}
* @description 设置图形中心点
* 提供rotate, scale and translate支持
* 添加图形及图形被拖动后将被调用
* @param {Event} 鼠标事件 (图形被添加时调用,该参数为null)
* @param {Graph} 当前图形实例
* @return {Undefined} 无返回值
*/
config = {
// ...,
setGraphCenter ([offsetX, offsetY], { style }) {
// style.graphCenter = [offsetX, offsetY]
}
}
move (Optional)
/**
* @type {Function}
* @description Moving graph,support for drag
* @param {Event} Mouse move Event
* @param {Graph} Current graph instance
* @return {Undefined} Void
*/
config = {
// ...,
move ([offsetX, offsetY], { shape }) {
// 一些操作...
}
}
扩展示例
import { extendNewGraph } from '@east-century/crender'
const circle = {
shape: {
rx: 0,
ry: 0,
r: 0
},
validator ({ shape }) {
const { rx, ry, r } = shape
if (typeof rx !== 'number' || typeof ry !== 'number' || typeof r !== 'number') {
console.error('Shape configuration is abnormal!')
return false
}
return true
},
draw ({ ctx }, { shape }) {
ctx.beginPath()
const { rx, ry, r } = shape
ctx.arc(rx, ry, r, 0, Math.PI * 2)
ctx.fill()
ctx.stroke()
ctx.closePath()
},
hoverCheck (position, { shape }) {
const { rx, ry, r } = shape
return checkPointIsInCircle(rx, ry, r, position)
},
setGraphCenter (e, { shape, style }) {
const { rx, ry } = shape
style.graphCenter = [rx, ry]
},
move ({ movementX, movementY }, { shape }) {
this.attr('shape', {
rx: shape.rx + movementX,
ry: shape.ry + movementY
})
}
}
extendNewGraph('circle', circle)
提供动画过渡数据 (animationCurve)。
如果你想扩展新的缓动曲线,请移步 扩展新曲线.
提供贝塞尔曲线支持,例如计算曲线长度,曲线折线互转。
提供了颜色计算,例如获取颜色的rgba值,以便于颜色动画状态的计算。