npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@east-century/crender

v0.0.1

Published

Canvas-based vector graphics rendering plugin

Downloads

4

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

原型方法

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

/**
 * @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 }) {
    // 一些操作...
  }
}

实例属性

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

/**
 * @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)
  • Transition

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

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

  • BezierCurve

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

  • Color

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