Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >[译] 使用 DOMMatrix 绘制一个星星

[译] 使用 DOMMatrix 绘制一个星星

作者头像
小弟调调
发布于 2023-09-24 06:45:16
发布于 2023-09-24 06:45:16
39200
代码可运行
举报
文章被收录于专栏:埋名埋名
运行总次数:0
代码可运行

使用 DOMMatrix 绘制一个星星 Drawing a star with DOMMatrix

最近我录制了一集关于 DOMPointDOMMatrix 的 HTTP 203 视频。如果你更喜欢观看视频版本,可以点击这里[1],但是请回到这里获取一些关于我犯了一个愚蠢错误的额外细节,而我几乎没有被发现。

I recently recorded an episode of HTTP 203 on DOMPoint and DOMMatrix. If you'd rather watch the video version, here it is, but come back here for some bonus details on a silly mistake I made, which I almost got away with.

DOMMatrix 允许你对 DOMPoints 应用变换。我发现这些 API 在绘制形状和处理变换结果时非常有用,而不会在 DOM 中引起完整的布局。

DOMMatrix lets you apply transformations to DOMPoints. I find these APIs handy for drawing shapes, and working with the result of transforms without causing full layouts in the DOM.

DOMPoint

这是 DOMPoint

Here's DOMPoint:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const point = new DOMPoint(10, 15); console.log(point.x); // 10 console.log(point.y); // 15 

是的!很令人兴奋,对吧?好的,也许 DOMPoint 单独来看并不那么有趣,所以让我们介绍一下 DOMMatrix

Yeah! Exciting right? Ok, maybe DOMPoint isn't interesting on its own, so let's bring in DOMMatrix:

DOMMatrix

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const matrix = new DOMMatrix('translate(10px, 15px)').scale(2); console.log(matrix.a); // 2; 

DOMMatrix 允许你创建一个矩阵,可以选择从 CSS 变换中创建,并对其执行额外的变换操作。每个变换都会创建一个新的 DOMMatrix,但也有其他可以直接修改矩阵的方法[2],比如 scaleSelf()

DOMMatrix lets you create a matrix, optionally from a CSS transform, and perform additional transforms on it. Each transform creates a new DOMMatrix, but there are additional methods that mutate the matrix, such as scaleSelf().

当你结合使用 DOMMatrixDOMPoint 时,事情变得有趣起来:

Things start to get fun when you combine DOMMatrix and `DOMPoint:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const newPoint = matrix.transformPoint(point); 

我曾经在 Squoosh[3] 上使用这个方法来绘制 blob 形状,最近我还用它来绘制一个星星。

I used this to draw the blobs on Squoosh, but even more recently I used it to draw a star.

Drawing a star 绘制一个星星

我需要一个中心点位于确切中心的星星。我可以下载一个星星图案并检查中心点,但为什么不自己绘制呢?星星只是一个有尖角的圆形,对吧?不幸的是,我不能记住这种类型的数学公式,但这并不重要,因为我可以让 DOMMatrix 来帮我完成。

I needed a star where the center was in the exact center. I could download one and check the center point, but why not draw it myself? A star's just a spiky circle right? Unfortunately I can't remember the maths for this type of thing, but that doesn't matter, because I can get DOMMatrix to do it for me.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const createStar = ({ points = 10, x = 0, y = 0, size = 1 }) =>   Array.from({ length: points }, (_, i) =>     new DOMMatrix()       .translate(x, y)       .scale(size)       .transformPoint({ x: 0, y: 0 }),   ); 

我正在使用 Array.from 创建和初始化一个数组。我希望有一种更友好的方式来做这个[4]。

I'm using Array.from to create and initialise an array. I wish there was a friendlier way to do this.

一个典型的星星有 10 个点 - 5 个外部点和 5 个内部点,但我觉得允许其他类型的星星也是不错的。

A typical star has 10 points – 5 outer points and 5 inner points, but I figured it'd be nice to allow other kinds of stars.

矩阵只有设置尺寸和位置的变换,所以它只会返回一堆以 x, y 为坐标的点。

The matrix only has transforms set to apply the size and position, so it's just going to return a bunch of points at x, y.

无论如何,这不会阻止我。我将在下面的 <svg> 元素中绘制它:

Anyway, I'm not going to let that stop me. I'm going to draw it in an <svg> element below:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const starPoints = createStar({ x: 50, y: 50, size: 23 }); const starPath = document.querySelector('.star-path'); starPath.setAttribute(   'd',   // SVG path syntax   `M ${starPoints.map((point) => `${point.x} ${point.y}`).join(', ')} z`, ); 

这是最终的结果:

And here's the result:

嗯,这是十个重叠在一起的点。并不完全是一个星星。好的,下一步:

So, err, that's 10 points on top of each other. Not exactly a star. Ok, next step:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const createStar = ({ points = 10, x = 0, y = 0, size = 1 }) =>   Array.from({ length: points }, (_, i) =>     new DOMMatrix()       .translate(x, y)       .scale(size)       // Here's the new bit!       // 这是新的部分!       .translate(0, -1)       .transformPoint({ x: 0, y: 0 }),   ); 

这是结果:

And the result:

使用滑块在前一个状态和新状态之间进行过渡。我相信你会同意这种互动是值得的。

Use the slider to transition between the previous and new state. I'm sure you'll agree it was worth making this interactive.

好的,现在所有的点仍然重叠在一起。让我们来修复一下:

Ok, so all the points are still on stop of each other. Let's fix that:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const createStar = ({ points = 10, x = 0, y = 0, size = 1 }) =>   Array.from({ length: points }, (_, i) =>     new DOMMatrix()       .translate(x, y)       .scale(size)       // Here's the new bit!       // 这是新的部分!       .rotate((i / points) * 360)       .translate(0, -1)       .transformPoint({ x: 0, y: 0 }),   ); 

我将每个点按照 360 度的一部分进行旋转。因此,第一个点旋转了 0/10 的 360 度,第二个点旋转了 1/10 的 360 度,然后是 2/10,以此类推。

I'm rotating each point by a fraction of 360 degrees. So the first point is rotated 0/10ths of 360 degrees, the second is rotated 1/10th, then 2/10ths and so on.

这是结果:

Here's the result:

现在我们有了一个形状!虽然不是一个星星,但我们正在取得进展。

Now we have a shape! It's not a star, but we're getting somewhere.

为了完成它,将一些点向外移动:

To finish it off, move some of the points outward:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const createStar = ({ points = 10, x = 0, y = 0, size = 1 }) =>   Array.from({ length: points }, (_, i) =>     new DOMMatrix()       .translate(x, y)       .scale(size)       .rotate((i / points) * 360)       // Here's the new bit!       // 这是新的部分!       .translate(0, i % 2 ? -1 : -2)       .transformPoint({ x: 0, y: 0 }),   ); 

这是结果:

Here's the result:

这就是一个星星!

And that's a star!

But then I messed it up 但后来我搞砸了

当我为《HTTP 203》节目准备幻灯片时,我意识到 points 参数不太对。它允许你像这样使用:

As I was getting the slides together for the HTTP 203 episode, I realised that the points argument wasn't quite right. It lets you do something like this:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const starPoints = createStar({ points: 9, x: 50, y: 50, size: 23 }); 

看起来像这样:

Which looks like this:

这...不是一个星星。要创建一个有效的星星,点的数量必须是偶数。此外,到目前为止,我们创建的十个点的形状通常称为“五角星”,所以我改变了 API 以符合这种风格:

Which… isn't a star. The number of points has to be even to create a valid star. Besides, the ten-pointed shape we've been creating so far is typically called a "five-pointed star", so I changed the API to work in that style:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const createStar = ({ points = 5, x = 0, y = 0, size = 1 }) =>   Array.from({ length: points * 2 }, (_, i) =>     new DOMMatrix()       .translate(x, y)       .scale(size)       .rotate((i / points) * 360)       .translate(0, i % 2 ? -1 : -2)       .transformPoint({ x: 0, y: 0 }),   ); 

我快速测试了一下代码,看起来没问题。但是...它还不太对。你能发现我引入的 bug 吗?我直到 Dillon Pentz 在 Twitter 上指出才注意到[5]:

I quickly tested the code, and it looked fine. But… it's not quite right. Can you see the bug I've introduced? I didn't notice it until Dillon Pentz pointed it out on Twitter[5]:

等等...如果数组循环中的索引满足 0 <= i < points * 2,那么通过 points 进行除法如何得到正确的星星呢?这样不是会围绕圆圈旋转两次吗? Wait… If the index in the array from loop is 0 <= i < points * 2, how does it produce the correct star when dividing by points? Doesn't that rotate around the circle twice?

他是对的!我在数组长度中正确地乘以了 points,但在 rotate 中忘记了这样做。我没有注意到它,因为对于奇数点的星星,它创建了一个几乎相同的形状。

And, he's right! I correctly multiply points for the array length, but I forgot to do it for the rotate. I didn't notice it, because for stars with odd-numbered points, it creates a shape that's almost identical.

上面的结果是我想要的。拖动滑块来查看代码实际上是如何工作的。

The above is the result I intended. Drag the slider to see what the code actually does.

这是一个正确的实现:

Here's a correct implementation:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const createStar = ({ points = 5, x = 0, y = 0, size = 1 }) => {   const length = points * 2;    return Array.from({ length }, (_, i) =>     new DOMMatrix()       .translate(x, y)       .scale(size)       .rotate((i / length) * 360)       .translate(0, i % 2 ? -1 : -2)       .transformPoint({ x: 0, y: 0 }),   ); }; 

我想故事的寓意是:不要在最后一刻改变幻灯片。

I guess the moral of the story is: Don't change slides at the last minute.

参考

  1. https://www.youtube.com/watch?v=VdNzD4lhidw&lc=Ugx4NRGM8QtqD5XwbEN4AaABAg
  2. https://drafts.fxtf.org/geometry/#dommatrix
  3. https://squoosh.app/
  4. https://es.discourse.group/t/provide-an-easy-way-to-create-a-new-array-filled-via-a-mapping-function/1056/56
  5. https://twitter.com/Dillon_Pentz/status/1574771164249227271 2
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-09-23 19:41,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JSdig 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
geopandas:Python绘制数据地图
GeoPandas是一个Python开源项目,旨在提供丰富而简单的地理空间数据处理接口。 GeoPandas扩展了Pandas的数据类型,并使用matplotlib进行绘图。GeoPandas官方仓库地址为:GeoPandas。 GeoPandas的官方文档地址为:GeoPandas-doc。 本文主要参考GeoPandas Examples Gallery。 GeoPandas的基础使用见Python绘制数据地图1-GeoPandas入门指北。 GeoPandas的可视化入门见Python绘制数据地图2-GeoPandas地图可视化。
luckpunk
2023/09/14
4.2K0
geopandas:Python绘制数据地图
写一个炫酷的个人名片页✨✨
在19年,我就写了一个较为炫酷的个人名片页。当时的我热衷于使用各种过渡效果,当然,也尝试了很多新鲜的 css 特性,例如为了实现多种主题色使用了 css 变量(好像还是我首次使用flex布局呢)
戴兜
2023/04/12
7600
写一个炫酷的个人名片页✨✨
Android多媒体之GLES2战记第四集--移形换影
这也就是m12,m13,m14,m15为什么特别,m0,m1,m2,m3为什么和x息息相关
张风捷特烈
2019/01/28
6100
Android多媒体之GLES2战记第四集--移形换影
HTML5 Canvas的简单使用
参考这里 https://www.runoob.com/w3cnote/html5-canvas-intro.html
不愿意做鱼的小鲸鱼
2022/09/24
1.6K0
HTML5 Canvas的简单使用
情人节程序员用HTML网页表白【粒子告白】 HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
1 网页简介:基于 HTML+CSS+JavaScript 制作七夕情人节表白网页、生日祝福、七夕告白、 求婚、浪漫爱情3D相册、炫酷代码 ,快来制作一款高端的表白网页送(他/她)浪漫的告白,制作修改简单,可自行更换背景音乐,文字和图片即可使用
IT司马青衫
2022/08/20
2.1K1
情人节程序员用HTML网页表白【粒子告白】 HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
【 开源计划 - Flutter组件 】 星星也可以如此闪耀 flutter_star
【pub地址 】 【github地址】 dependencies: flutter_star: $lastVersion ---- 一、描述 目标: 使用canvas手工打造,一个完美的星星评分组件。 ---->[StarScore 星星显示组件]---- [1] 比如显示4.2: 会有5颗星, 前四颗填满,后一刻填充20% StarScore 为 Stateless组件,仅负责显示的需求 ---->[CustomRating 星星评分组件]---- [2] 可指定最大值,也就是显示多少个星星 [
张风捷特烈
2020/04/30
1K0
【  开源计划 - Flutter组件 】 星星也可以如此闪耀 flutter_star
Flutter 绘制实践 | 路径篇 · 数字显示管
欢迎来到 Flutter 绘制实践系列,本文有 文章版 和 视频版。视频发布在 bilibli 同名账号下,文章首发于掘金平台。今天来的话题是: 数字显示管 , 如下所示,展示 0~9 十个数字:
张风捷特烈
2023/02/15
7230
Flutter 绘制实践 | 路径篇 · 数字显示管
OpenHarmony定义可动画属性:@AnimatableExtend装饰器
@AnimatableExtend装饰器用于自定义可动画的属性方法,在这个属性方法中修改组件不可动画的属性。在动画执行过程时,通过逐帧回调函数修改不可动画属性值,让不可动画属性也能实现动画效果。
小帅聊鸿蒙
2025/05/13
660
OpenHarmony定义可动画属性:@AnimatableExtend装饰器
Flutter 绘制集录 | 第四画 - 风车
最近源码看得比较多,本文来画点东西调节下心情,本绘制已收录于 FlutterUnit 的绘制集录,本文源码可参见【windmill.dart】 。绘制内容非常简单,如下所示,两个样式的小风车:通过这两个小例子,可以学到:
张风捷特烈
2022/11/18
6340
Flutter 绘制集录 | 第四画 - 风车
现在前端都流行手写ECharts ?
绘制的底层是强大的,我们所用的各端语言只是在现代UI追求的步伐中和用户喜好的交互中求同存异,抽取封装出自成个性风格的UI控件,当然面对万亿级别的客户各个平台的UI库出也不可能满足所有的客户需求,当然一门语言的可制定性也意味着其强大,几乎每个平台都提供了接口让开发者创造其UI的可能性,更可能的能满足客户需求。ECharts作为前端强大的图表K线等绘制工具可以说应有竟有,无比风骚。但用户和产品的需求永远是一个库满足不了的。当然作为技术人员自定义绘制也应该是需要掌握的技术。我们前端移动端作为产品的排面就应该让其独具特色,别具一格。所以自定义从我们的技术岗位、技术本身、亿万用户不同需求...出发,"自定义很必要"。
小丑同学
2021/05/18
3.7K0
现在前端都流行手写ECharts ?
【愚公系列】2023年12月 GDI+绘图专题 Matrix
WinForm中的Matrix是一个矩阵类,用于表示二维矩阵。它属于System.Drawing命名空间下的Matrix类。Matrix类表示一个二维仿射变换矩阵,其中包含有关旋转、平移、缩放和倾斜的信息。这个类可以用于WinForm中的图形变换、图形绘制以及几何计算等方面。
愚公搬代码
2023/12/27
3020
几条曲线构建Android表白程序
每年的情人节和七夕,甜蜜与痛苦的日子,做点什么好呢? 写诗画画送礼物,逛街吃饭看电影? 作为搬砖爱好者,写个表白脚本或者动画什么的吧。 想起之前看到的一段H5动画,在Android平台“临摹”了一遍。 效果如下图:其构图还是比较简单的,树枝加上由心形花瓣构成的心形树冠(后面做成动画之后会有随机的花瓣飘落)。
用户1269200
2018/07/30
8330
几条曲线构建Android表白程序
Wendy Shijia 的「 Escher's Gallery」可视化作品复现系列文章(三)
网页演示:https://desertsx.github.io/dataviz-in-action/02-eschers-gallery/index.html
古柳_DesertsX
2020/12/21
6970
Wendy Shijia 的「 Escher's Gallery」可视化作品复现系列文章(三)
HenCoder Android 开发进阶:自定义 View 1-4 Canvas 对绘制的辅助
这期是 HenCoder 自定义绘制的第 1-4 期:Canvas 对绘制的辅助——范围裁切和几何变换。
扔物线
2018/08/20
7850
HenCoder Android 开发进阶:自定义 View 1-4 Canvas 对绘制的辅助
SVG绘制星空效果
主要代码: 代码详见GitHub:https://github.com/toly1994328/svg-night: svg星空 <!DOCTYPE html> <html lang="en">
张风捷特烈
2018/09/26
1.4K0
WebGL简易教程(七):绘制一个矩形体
在上一篇教程《WebGL简易教程(六):第一个三维示例(使用模型视图投影变换)》中,通过使用模型视图投影变换,绘制了一组由远及近的三角形。但是这个示例还是太简单了,这几个三角形的坐标仍然是-1到1之间的坐标,无论如何都是很容易设置参数的,可能并不能很深入的理解模型视图投影变换。
charlee44
2019/10/08
1.8K0
WebGL简易教程(七):绘制一个矩形体
面向对象+模块化设计绘制canvas星空动画
require.js的相关内容已在我的博文 《requireJs的使用,以canvas绘制星空为例》中描述, 可查看:https://cloud.tencent.com/developer/article/1040858 下面说一下面向对象设计canvas绘制星空的各种对象。 1、静态元素 如背景(Backgound)、土地(Land)、房屋(House)、大树(Tree),这些元素的属性如坐标(x,y)、长度(width)、高度(height)等信息是固定不变,因此我们只用向其绘制函数内传入常量参数就可以
lonelydawn
2018/02/09
2.1K0
“AS3.0高级动画编程”学习:第一章高级碰撞检测
AdvancED ActionScript 3.0 Animation 是Keith Peters大师继"Make Things Move"之后的又一力作,网上已经有中文翻译版本了,打算下一阶段开始啃这本书。 今天开始学习高级碰撞检测,所用到的预备知识: 1、BitmapData的透明与不透明区别 位图数据(BitmapData)有二种模式,一种支持透明(即每个像素的值采用AARRGGBB这种32位颜色表示);另一种不支持透明度(即传统的RRGGBB这种24位颜色表示,简单点讲就是alpha分量默认为FF,
菩提树下的杨过
2018/01/19
1.5K0
72.HarmonyOS NEXT PicturePreviewImage组件深度剖析:手势交互与动画系统深度解析 (二)
全栈若城
2025/03/15
1480
【愚公系列】2024年02月 WEBGL专题-图形矩阵组合
这些操作常常用于计算机图形学、图像处理等领域中的图像变换。图形平移、缩放、旋转是计算机图形学中常用的操作,用来改变图像的位置、大小和方向。
愚公搬代码
2025/05/28
490
【愚公系列】2024年02月 WEBGL专题-图形矩阵组合
推荐阅读
相关推荐
geopandas:Python绘制数据地图
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验