D3 路径模块

d3

D3 路径模块

D3 提供了基本图元模块 d3-path 用于将画布 Canvas 绘制路径的方法序列化 serialize,转换为适用于 SVG 作为路径元素 path 的属性 d 的字符串。

参考

基于该模块所编写的(路径绘制)代码,可以轻松地实现在画布和 svg 两种不同的环境的适配,就可以做到一份代码在两种不同的渲染环境画出相同的路径形状

js
// 传入的参数 context 是路径序列化器
// 该方法是设置路径序列化器,让它在画布中绘制一个圆
function drawCircle(context, radius) {
  context.moveTo(radius, 0);
  context.arc(0, 0, radius, 0, 2 * Math.PI);
}

const context = d3.path();
// 配置路径序列化器
// 生成在画布 canvas 上绘制路径的指令/命令/方法
drawCircle(context, 40);
// 通过调用路径序列化器的方法 context.toString() 将在画布中绘制路径的方法转换为字符串
// 可以应用到 svg 的 <path> 元素的属性 d 上
pathElement.setAttribute("d", context.toString());

该模块所提供的 API

  • d3.path() 创建一个(画布)路径绘制方法的序列化器(以下简称为 path 路径序列化器)
提示

D3 提供了另一种方法 d3.pathRound(number) 用于创建序列化器

该方法和 d3.path() 类似,也具有相同的方法,可以调用它们在画布中绘制路径;也具有 path.toString() 方法将绘制方法序列化为字符串

所不同的是 d3.pathRound(number) 可以接受一个参数,其值是数字,用于约束/限制转换/序列化为字符串时的坐标精度,通过设置数值的精度可以调整所生成的字符串的大小

参数 number 的默认值为 3, 即转换为字符串时其中关于坐标的数值,其小数点后最大保留位数为千分位

序列化器是一个对象,提供了一系列的方法,可以调用它们在画布中绘制路径(它们与画布上下文 context 所提供的绘制路径的原生方法一一对应)

在画布中绘制路径的原生方法

在画布 canvas 中可以调用一系列相关的方法,通过 创建路径 Path 来创作出一个复杂的形状

以下是一些常用于在画布上绘制路径的方法:

  • 使用 canvas 对象(内容)方法 beginPath() 「声明」需要创建一个新的路径
  • 配合使用canvas 对象(内容)方法 moveTo(x, y)lineTo(x, y) 创建路径,前一个方法确定路径开始点,后一个方法基于上方的坐标和该方法给出的坐标之间创建一条路径
  • 使用 canvas 对象(内容)方法 fill()stroke() 结束路径并创建实心或空心的图形
js
// 绘制一个正方形(仅有描边,不带填充)
ctx.strokeRect(50, 50, 100, 100);

// 绘制路径
ctx.beginPath();
ctx.moveTo(75, 75);
ctx.lineTo(125, 75);
ctx.lineTo(125, 125);
ctx.lineTo(75, 75);
ctx.fill();
  • path.moveTo(x, y) 移动画笔到画布中指定的点 (x, y)
    相当于画布上下文 context 的原生方法 context.moveTo
    如果进行序列化,则对应于 SVG 的路径字符串的移动命令 Mm
  • path.lineTo(x, y) 从当前位置绘制一条线到指定的点 (x, y)
    相当于画布上下文 context 的原生方法 context.lineTo
    如果进行序列化,则对应于 SVG 的路径字符串的移动命令 LlHh,以及 Vv
  • path.rect(x, y, w, h) 以四个点 (x, y)(x+w, y)(x+w, y+h)(x, y+h) 为顶点绘制一个四边形
    相当于画布上下文 context 的原生方法 context.rect
    如果进行序列化,则对应于 SVG 的路径字符串的移动命令 LlHh,以及 Vv
  • path.quadraticCurveTo(cpx, cpy, x, y) 从当前位置绘制一条二次贝塞尔曲线 Quadratic Bézier curve 到指定点 (x, y),其中控制点为 (cpx, cpy)
    相当于画布上下文 context 的原生方法 context.quadraticCurveTo
    如果进行序列化,则对应于 SVG 的路径字符串的移动命令 Qq,以及 Tt
  • path.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y) 从当前位置绘制一条三次贝塞尔曲线 Cubic Bézier curve 到指定点 (x, y),其中两个控制点为 (cpx1, cpy1)(cpx2, cpy2)
    相当于画布上下文 context 的原生方法 context.bezierCurveTo
    如果进行序列化,则对应于 SVG 的路径字符串的移动命令 Cc,以及 Ss
  • path.arc(x, y, radius, startAngle, endAngle[, anticlockwise]) 绘制一条弧线
    (x, y) 作为中心点,以 radius 为半径,以 startAngle 为起始角,以 endAngle 为终止角绘制一段圆弧。如果 anticlockwisetrue,则以逆时针方向绘制圆弧;否则以顺时针方向绘制。
    如果当前点不等于圆弧起点,则从当前点绘制一条直线到圆弧起点。
    相当于画布上下文 context 的原生方法 context.arc
    如果进行序列化,则对应于 SVG 的路径字符串的移动命令 Aa
  • path.arcTo(x1, y1, x2, y2, radius) 从当前的点开始绘制一条弧形
    • 参数 radius 是弧形的半径
    • 参数指定的点 (x1, y1) 与当前点(开始点)所连成的直线,与圆弧相切
    • 参数指定的点 (x1, y1)(x2, y2)(结束点)所连成的直线,与圆弧相切

    如果第一个切点与当前点(开始点)不一致,则会在当前点和第一个切线点之间绘制一条直线。
    相当于画布上下文 context 的原生方法 context.arcTo
    如果进行序列化,则对应于 SVG 的路径字符串的移动命令 Aa
  • path.closePath() 结束当前的路径,并自动从当前的点到路径的初始点绘制一条直线,使得路径可以构成一个封闭的形状
    相当于画布上下文 context 的原生方法 context.closePath
    如果进行序列化,则对应于 SVG 的路径字符串的结束命令 Zz

另外序列化器还有一个核心方法,用于将绘制方法转换/序列化为字符串

  • path.toString() 将序列化器(依次)设置的一系列方法(这些方法可直接在画布 canvas 上绘制出路径),转换为字符串形式,可用于 SVG 的元素 <path> 的属性 d 的属性值
Path2D

JS 原生提供了一个称为 Path2D 的类,它的实例化对象 new Path2D() 可以调用画布上下文 context 的一些方法,在画布上绘制路径

另外它还有一个功能,在实例化时支持传入 SVG 的路径字符串 new Path2D(pathString) 将其转换为画布的路径绘制方法,这和 path.toString() 的作用相反

js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

//
let p = new Path2D("M10 10 h 80 v 80 h -80 Z");
ctx.fill(p); // 根据 SVG 的路径字符串,在画布中绘制出一个正方形

Copyright © 2024 Ben

Theme BlogiNote

Icons from Icônes