当前位置: 首页 > 工具软件 > Two.js > 使用案例 >

使用Two.js绘制2D图形的初学者指南

孔硕
2023-12-01

Two.js一个API,可轻松使用代码创建2D形状。 继续学习,您将学习如何从JavaScript创建形状和设置动画效果。

Two.js与渲染器无关,因此您可以依靠相同的API使用Canvas,SVG或WebGL进行绘制。 该库具有许多方法,可用于控制不同形状在屏幕上的显示方式或动画形式。

安装

库的未压缩版本的大小约为128 KB,而压缩版本为50 KB。 如果使用的是最新版本,则可以使用自定义版本进一步减小库的大小。

您可以从GitHub下载该库的缩小版本 ,也可以直接链接到CDN托管版本 。 将库添加到网页后,就可以开始绘制和设置不同形状或对象的动画。

创建基本形状

首先,您需要告诉Two.js有关要在其上绘制形状和设置其动画的元素。 您可以将一些参数传递给Two构造函数进行设置。

使用type属性设置渲染器的type 。 您可以指定一个值,例如svgwebglcanvas等。默认情况下, type设置为svg 。 可以使用widthheight参数指定绘图空间的widthheight 。 您还可以使用fullscreen参数将绘图空间设置为fullscreen 。 当fullscreen设置为true时, widthheight的值将被忽略。

最后,您可以告诉Two.js在布尔autostart参数的帮助下自动启动动画。

将所有需要的参数传递给构造函数后,您可以开始绘制线条,矩形,圆形和椭圆形。

您可以使用two.makeLine(x1, y1, x2, y2)画一条线。 在此, (x1, y1)是第一端点的坐标, (x2, y2)是第二端点的坐标。 此函数将返回Two.Line对象,该对象可以存储在变量中,以便在以后进行进一步操作。

以类似的方式,您可以分别使用two.makeRectangle(x, y, width, height)two.makeRoundedRectangle(x, y, width, height, radius)绘制法线和圆角矩形。 请记住, xy确定矩形的中心,而不是像许多其他库一样确定矩形的左上角坐标。 widthheight参数将确定矩形的大小。 radius参数用于指定圆角的半径值。

您还可以分别使用two.makeCircle(x, y, radius)two.makeEllipse(x, y, width, height)在网页上绘制圆形和椭圆形。 就像矩形一样, xy参数指定圆或椭圆的中心。 在椭圆的情况下,将widthheight设置为相同的值将使其像一个圆形。

在Two.js中,您将经常使用的一种有用方法是two.makeGroup(objects) 。 您可以传递不同对象的列表,也可以传递对象,路径或组的数组作为此方法的参数。 它还将返回Two.Group对象。

操作组中的对象

创建组后,您可以使用该组提供给您的属性立即操纵其所有子级。

strokefill属性可用于设置组中所有子项的笔触和填充颜色。 他们将接受您可以在CSS中表示颜色的所有有效形式。 这意味着您可以自由使用RGB,HSL或十六进制表示法。 您也可以简单地使用颜色的名称,例如orangeredblue 。 同样,您可以为所有其他属性(如linewidthopacitymitercap设置值。 可以使用noFill()noStroke()方法从组中的所有子项中删除填充和描边。

您还可以应用其他物理变换,例如scalerotationtranslation 。 这些转换将应用于单个对象。 使用add()remove()类的方法很容易将新对象添加到组中并删除它们。

定义渐变和编写文本

您可以在Two.js中定义线性和径向渐变。 定义渐变并不意味着它将自动在屏幕上呈现,但是在设置各种对象的fillstroke值时将可以使用它。

您可以使用two.makeLinearGradient(x1, y1, x2, y2, stops)定义线性渐变。 值x1y1确定渐变起点的坐标。 类似地,值x2y2确定渐变终点的坐标。 所述stops参数是阵列Two.Stop实例。 这些定义了数组每个部分的颜色以及每种颜色过渡到下一个颜色的位置。 可以使用new Two.Stop(offset, color, opacity)定义它们,其中offset确定渐变上必须完全渲染特定颜色的点。 color参数确定特定点处渐变的颜色。 您可以使用任何有效CSS颜色表示形式作为其值。 最后, opacity参数确定颜色的不透明度。 不透明度是可选的,它可以具有0到1之间的任何值。

您可以使用two.makeRadialGradient(x, y, radius, stops, fx, fy)以类似的方式定义径向渐变。 在这种情况下,值xy确定梯度的中心。 radius参数指定渐变应延伸多远。 您也可以将停止点数组传递给此方法,以设置渐变的颜色组成。 参数fxfy是可选的,它们可用于指定渐变的焦点位置。

在下面的CodePen中检查一些渐变类型及其代码。

请记住,渐变的xy位置是相对于它们要填充的形状的原点而言的。 例如,假定从中心填充形状的径向渐变将始终将xy设置为零。

Two.js还允许您在绘图区域上编写文本,并根据需要稍后进行更新。 这需要使用two.makeText(message, x, y, styles) 。 从参数名称可以明显看出message是您要编写的实际文本。 参数xy是将用作书写文本中心的点的坐标。 styles参数是一个对象,可用于设置大量属性的值。

您可以使用样式来设置属性值,例如字体familysizealignment 。 您还可以指定属性的值,例如fillstrokeopacityrotationscaletranslation

创建一个Two.js项目

了解了所有这些方法和属性之后,该将它们应用于项目了。 在本教程中,我将向您展示如何使用Two.js来绘制周期表的前十个元素,其中电子围绕原子核旋转。 原子核也将有一些轻微的运动,以改善我们的表示的视觉吸引力。

我们首先定义一些变量和函数,这些变量和函数将在以后使用。

var centerX = window.innerWidth / 2;
var centerY = window.innerHeight / 2;

var elem = document.getElementById("atoms");

var elementNames = [
  "",
  "Hydrogen",
  "Helium",
  "Lithium",
  "Beryllium",
  "Boron",
  "Carbon",
  "Nitrogen",
  "Oxygen",
  "Fluorine",
  "Neon"
];

var styles = {
  alignment: "center",
  size: 36,
  family: "Lato"
};

var nucleusCount = 10;
var nucleusArray = Array();

var electronCount = 10;
var electronArray = Array();

function intRange(min, max) {
  return Math.random() * (max - min) + min;
}

上面的代码将窗口中心的坐标存储在变量centerXcenterY 。 这些将在以后用于将我们的原子放置在中心。 elementNames数组包含元素周期表的前十个元素的名称。 每个名称的索引对应于该元素的电子和质子数,并且以空字符串开头。 styles对象包含用于设置文本对象样式的属性。

我们还定义了一个函数intRange()以在给定的极限内获得随机整数值。

var two = new Two({ fullscreen: true }).appendTo(elem);

var protonColor = two.makeRadialGradient(
  0,
  0,
  15,
  new Two.Stop(0, "red", 1),
  new Two.Stop(1, "black", 1)
);

var neutronColor = two.makeRadialGradient(
  0,
  0,
  15,
  new Two.Stop(0, "blue", 1),
  new Two.Stop(1, "black", 1)
);

for (i = 0; i < nucleusCount; i++) {
  nucleusArray.push(two.makeCircle(intRange(-10, 10), intRange(-10, 10), 8));
}

nucleusArray.forEach(function(nucleus, index) {
  if (index % 2 == 0) {
    nucleus.fill = protonColor;
  }
  if (index % 2 == 1) {
    nucleus.fill = neutronColor;
  }
  nucleus.noStroke();
});

这将创建2的实例并定义两个径向渐变。 红色/黑色的径向渐变代表质子,蓝色/黑色的渐变代表中子。

我们已经使用intRange()函数将所有这些中子和质子彼此放置在20个像素之内。 makeCircle()方法还将这些质子和中子的半径设置为10个像素。 之后,我们遍历nucleusArray并用不同的渐变交替填充每个圆。

for (var i = 0; i < 10; i++) {
  if (i < 2) {
    var shellRadius = 50;
    var angle = i * Math.PI;
    electronArray.push(
      two.makeCircle(
        Math.cos(angle) * shellRadius,
        Math.sin(angle) * shellRadius,
        5
      )
    );
  }
  if (i >= 2 && i < 10) {
    var shellRadius = 80;
    var angle = (i - 2) * Math.PI / 4;
    electronArray.push(
      two.makeCircle(
        Math.cos(angle) * shellRadius,
        Math.sin(angle) * shellRadius,
        5
      )
    );
  }
}

将中子和质子置于核内很容易。 但是,正确地将电子以均匀的距离放置将需要一些数学运算。 我们使用shellRadius变量指定不同电子壳与原子核的距离。 整个圆的角度等于2 PI弧度。 我们可以通过均匀分布两个PI弧度来均匀地放置不同的电子。

Math.cos()Math.sin()函数用于根据角度区分不同电子位置矢量的垂直分量和水平分量。

var orbitA = two.makeCircle(centerX, centerY, 50);
orbitA.fill = "transparent";
orbitA.linewidth = 2;
orbitA.stroke = "rgba(0, 0, 0, 0.1)";

var orbitB = two.makeCircle(centerX, centerY, 80);
orbitB.fill = "transparent";
orbitB.linewidth = 2;
orbitB.stroke = "rgba(0, 0, 0, 0.1)";

var groupElectronA = two.makeGroup(electronArray.slice(0, 2));
groupElectronA.translation.set(centerX, centerY);
groupElectronA.fill = "orange";
groupElectronA.linewidth = 1;

var groupElectronB = two.makeGroup(electronArray.slice(2, 10));
groupElectronB.translation.set(centerX, centerY);
groupElectronB.fill = "yellow";
groupElectronB.linewidth = 1;

var groupNucleus = two.makeGroup(nucleusArray);
groupNucleus.translation.set(centerX, centerY);

该部分代码将来自不同壳的电子以及中子和质子置于各自独立的组中。 它还可以立即设置特定轨道中所有电子的填充色。

two
  .bind("update", function(frameCount) {
    groupElectronA.rotation += 0.025 * Math.PI;
    groupElectronB.rotation += 0.005 * Math.PI;
    groupNucleus.rotation -= 0.05;
  })
  .play();

var text = two.makeText("", centerX, 100, styles);

nucleusArray.forEach(function(nucleus, index) {
  nucleus.opacity = 0;
});

electronArray.forEach(function(electron, index) {
  electron.opacity = 0;
});

该部分代码将单个电子和质子的不透明度设置为零。 它还告诉Two.js以特定速度旋转电子和质子。

visible = 0;

document.addEventListener("click", function(event) {
  if (visible < nucleusArray.length) {
    nucleusArray[visible].opacity = 1;
    electronArray[visible].opacity = 1;
    visible++;
    text.value = elementNames[visible];
  }
  else {
    nucleusArray.forEach(el => el.opacity=0);
    electronArray.forEach(el => el.opacity=0);
    visible = 0;
    text.value = elementNames[0];
  }
});

代码的最后一部分使我们可以通过单击鼠标或点击来遍历元素。 为了加载下一个元素,我们使一个电子和一个质子或中子可见,并更新元素名称。 单击最后一个元素后,所有粒子再次被隐藏,因此我们可以重新开始。 visible变量跟踪当前可见的原子粒子的数量,以便我们可以相应地显示或隐藏它们。

尝试单击或点击下面的CodePen演示以查看周期表的前十个元素。

最后的想法

我们从本教程开始,简要介绍了Two.js库以及如何使用它来绘制矩形,圆形和椭圆形等形状。 之后,我们讨论了如何将不同的对象组合在一起以一次操纵它们。 我们使用此功能对元素进行分组,以同步平移和旋转它们。 这些工具全部都加入了元素周期表中前十个元素的原子动画中。

如您所见,使用Two.js创建动画2D图形非常容易。 这篇文章的重点是帮助您快速入门,因此我们仅介绍了基础知识。 但是,您应该阅读官方文档以了解有关该库的更多信息!

翻译自: https://code.tutsplus.com/tutorials/a-beginners-guide-to-drawing-2d-graphics-using-twojs--cms-31681

 类似资料: