You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

37 KiB

ENGLISH

CRender

Travis CI LICENSE version

CRender是干什么的?

  • 它是一个基于canvas矢量图形渲染插件。
  • 它对图形提供动画和鼠标事件支持。

npm安装

$ npm install @jiaminghi/c-render

快速体验

<!--资源位于个人服务器仅供体验和测试,请勿在生产环境使用-->
<!--调试版-->
<script src="http://lib.jiaminghi.com/crender/crender.map.js"></script>
<!--压缩版-->
<script src="http://lib.jiaminghi.com/crender/crender.min.js"></script>
<script>
  const { CRender, extendNewGraph } = window.CRender
  // do something
</script>

详细文档及示例请移步HomePage.


使用

import CRender from '@jiaminghi/c-redner'

const canvas = document.getElementById('canvas')

// 实例化 CRender
const render = new CRender(canvas)

// 向render中添加图形
const circle = render.add({ name: 'circle', ... })

Class CRender

/**
 * @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 = [300100]
 */

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}
 */

原型方法

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 () {
	// ...
}

Class Graph

实例属性

当添加一个图形时,你可以配置这些属性。

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

启用图形的mouseEntermouseOuterclick等事件支持需要将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 }) {
    // 一些操作...
  }
}

Class Style

实例属性

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

gradientColorgradientParams被配置后将自动启用渐变

原型方法

  • getStyle

    获取图形当前样式配置

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 '@jiaminghi/c-render'

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 '@jiaminghi/c-render'

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)

相关支持

  • Transition

    提供动画过渡数据 (animationCurve)。

    如果你想扩展新的缓动曲线,请移步 扩展新曲线.

  • BezierCurve

    提供贝塞尔曲线支持,例如计算曲线长度,曲线折线互转。

  • Color

    提供了颜色计算例如获取颜色的rgba值以便于颜色动画状态的计算。