<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: HandsomeTan</title>
    <description>The latest articles on DEV Community by HandsomeTan (@handsometan).</description>
    <link>https://dev.to/handsometan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2130125%2F3f4b1568-6691-45bb-a35f-cc988928c240.jpeg</url>
      <title>DEV Community: HandsomeTan</title>
      <link>https://dev.to/handsometan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/handsometan"/>
    <language>en</language>
    <item>
      <title>Three.js: How to determine if a point is inside a box?</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Tue, 23 Sep 2025 00:31:34 +0000</pubDate>
      <link>https://dev.to/handsometan/threejs-how-to-determine-if-a-point-is-inside-a-box-1fpi</link>
      <guid>https://dev.to/handsometan/threejs-how-to-determine-if-a-point-is-inside-a-box-1fpi</guid>
      <description>&lt;p&gt;Usually, a point's position is in world space. To check if it's inside a box, we need to transform it into the box's local coordinate system. We do this by multiply the point's world coordinates by box's inverse transformation matrix. This matrix converts from world space to the box's local space.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// get the box's inverse transformation matrix
const inverseMatrix = new THREE.Matrix4().copy(box.matrixWorld()).invert();

// transform the point to the box's local space
const localPoint = point.clone().applyMatrix4(inverseMatrix);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this transformation, we get the point position relative to the box's local coordinates. Then. we simply check if the new local position is within the box's bounding dimensions(comparing against the box's min and max values). If all coordinates(x, y, z) are within the box's bounds, the point is inside.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// get the box's bounding box in local space
const boxGeometry = box.geometry;
boxGeometry.coumputeBoundingBox();
const bbox = boxGeometry.boundingBox;

// check if the point is within bounds
bbox.containsPoint(localPoint);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Understanding Transformation Matrices in Computer Graphics</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Mon, 10 Mar 2025 04:31:42 +0000</pubDate>
      <link>https://dev.to/handsometan/understanding-transformation-matrices-in-computer-graphics-2f55</link>
      <guid>https://dev.to/handsometan/understanding-transformation-matrices-in-computer-graphics-2f55</guid>
      <description>&lt;p&gt;&lt;code&gt;Tanslate, rotate and scale&lt;/code&gt; are common operations in computer graphics , which are used to transfor objects.&lt;br&gt;
All transformations mentioned above are based on matrix multiplication, where each transformation is represented by a matrix. As we know, matrix multiplication is not commutative, so the orders of transformations matters.&lt;br&gt;
In many graphics application,  an object's center is located at its coordinate origin. Rotation and scaling can change an object's coordinate system, while translation only changes the object's origin.&lt;br&gt;
Let's consider the following css3 example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.box {
width: 100px;
height: 100px;
background-color: #000;
transform:  rotateY(45deg) translateX(50px);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;rotateY(45deg)&lt;/code&gt; : The coordnate system of box also applied this transformation, rotating 45 degrees clockwise, so its x-axis points at clockwise 45deg angle. Then, when applying &lt;code&gt;translate(50px)&lt;/code&gt;, the box will translate 50px along rotated x-axis instead of original horizontal axis.&lt;br&gt;
Now consider another case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.box {
width: 100px;
height: 100px;
background-color: #000;
transform:  scaleX(2) translateX(50px);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Would you think that box translate 50px or 100px on x-axis? the answer is 100px, because &lt;code&gt;scale(2)&lt;/code&gt; doubles the size of x-axes, so &lt;code&gt;translateX(50px)&lt;/code&gt;  is actually equivalent to &lt;code&gt;translate(100px)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By the way, the order of transformation in three.js is not affected by the order in which you set the properties because Three.js recalculates the object's transformation matrix lazily(only when needed, such as during rendering).  In Three.js, the transformation matrix for an object is computed as follows:&lt;br&gt;
&lt;code&gt;Matrix=Translation×Rotation×Scale&lt;/code&gt;&lt;br&gt;
This means that the object is scaled first, then rotated, and finally translated, regardless of the order in which you set  the properties. However, if you use methods like &lt;code&gt;translate(X/Y/Z)&lt;/code&gt; and &lt;code&gt;rotate(X/Y/Z)&lt;/code&gt;, the transformation for an object is applied immediately, so the order in which you set the properties matters in this case.&lt;/p&gt;

</description>
      <category>graphic</category>
    </item>
    <item>
      <title>WebGL - Coordinate systems</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Fri, 07 Mar 2025 09:50:48 +0000</pubDate>
      <link>https://dev.to/handsometan/webgl-coordinate-systems-23g2</link>
      <guid>https://dev.to/handsometan/webgl-coordinate-systems-23g2</guid>
      <description>&lt;p&gt;I was recently asked about coordinate systems used in WebGL, so I decided to summarize them below:&lt;br&gt;
There are six coordinate systems in WebGL:&lt;br&gt;
&lt;strong&gt;Local space&lt;/strong&gt;: an object made up of vertices has its own coordinate system, which is used to define the the position of its vertices relative to the object itself.&lt;br&gt;
&lt;strong&gt;World space&lt;/strong&gt;: The one consisting of all its objects, which is used for to define the position of an object within the scene&lt;br&gt;
&lt;strong&gt;View space&lt;/strong&gt;: It represent the field of view of a camera.similar to how human eyes perceive the world.&lt;br&gt;
&lt;strong&gt;Clip space&lt;/strong&gt;: a space defined by a specific viewing area&lt;br&gt;
&lt;strong&gt;NDC(Normal Device Coordinate) space&lt;/strong&gt;: a normalized space where coordinates range from -1 to 1 on the x and y axes.&lt;br&gt;
&lt;strong&gt;Screen space&lt;/strong&gt;: it is a final 2D space where objects are rendered onto the WebGL canvas.&lt;br&gt;
﻿&lt;br&gt;
Vertex postion is always represented by a four-dimensional vector (x, y, z, w) before being transformed into NDC space.&lt;br&gt;
&lt;code&gt;gl_position&lt;/code&gt; is sent to NDC space that uses left-handed coordinate system, and is then transformed into right-handed coordinate system through the multiplication of Model-View-Projection(mvp) matrix and &lt;code&gt;gl_position&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;there is an illustration showing the transformation between coordinate systems in &lt;em&gt;WebGL Programming Guide&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc13be5jl1xcut0w3sjz0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc13be5jl1xcut0w3sjz0.png" alt="Image description" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webgl</category>
    </item>
    <item>
      <title>Three.js: The Pitfall of Modifying Objects During traverse()</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Thu, 27 Feb 2025 14:05:32 +0000</pubDate>
      <link>https://dev.to/handsometan/threejs-the-pitfall-of-modifying-objects-during-traverse-4fl6</link>
      <guid>https://dev.to/handsometan/threejs-the-pitfall-of-modifying-objects-during-traverse-4fl6</guid>
      <description>&lt;p&gt;I encountered an issue when I tried to remove the scene's children using traverse() as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scene.traverse((child) =&amp;gt; {
    if (child.isNew) {
        scene.remove(child); // Modifies the scene's children array
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;running this code snippet, only one scene's child was removed. I ask deepseek what the issue was, and I summarize its reply as follows:&lt;br&gt;
Object3D.traverse() is a dynamic process, so the length of the children array change dynamically. When a child is removed, the array length used by the iteration process will be decreased by one, causing the traversal iteration to go wrong.&lt;/p&gt;

&lt;p&gt;the solution is to avoid modifying scene's children during traversal process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const childrenToRemove = [];

// Collect children to remove
scene.traverse((child) =&amp;gt; {
    if (child?.isNew) {
        childrenToRemove.push(child);
    }
});

// Remove collected children
for (const child of childrenToRemove) {
    scene.remove(child);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;by the way, there is a note in Three.js official document: &lt;code&gt;Note: Modifying the scene graph inside the callback is discouraged.&lt;/code&gt; honestly, I didn't fully understand what that meant until this issue occurred.&lt;/p&gt;

</description>
      <category>threejs</category>
    </item>
    <item>
      <title>three.js, all parameters about depth test</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Sat, 04 Jan 2025 03:47:24 +0000</pubDate>
      <link>https://dev.to/handsometan/threejs-all-parameters-about-depth-test-2b6e</link>
      <guid>https://dev.to/handsometan/threejs-all-parameters-about-depth-test-2b6e</guid>
      <description>&lt;p&gt;&lt;strong&gt;introduction to depth test:&lt;/strong&gt;&lt;br&gt;
Simply put, 'depth test'(except transparent cases):  if a object set depthTest to true, then its own depth value is required to compare with another in &lt;code&gt;depth buffer&lt;/code&gt; that cooresponds to it in position, and if it is closer from screen(default comparasion method) and its &lt;code&gt;depthWrite&lt;/code&gt; is set to true, so the depth value in &lt;code&gt;depth buffer&lt;/code&gt; will be replaced with its depth value, so that it is capable to display on screen. If &lt;code&gt;depthTest&lt;/code&gt; is set false, drawing order is that the next one covering the previous one.&lt;br&gt;
﻿&lt;br&gt;
parameters affected on depth test have: &lt;code&gt;depthTest&lt;/code&gt;, &lt;code&gt;depthWrite&lt;/code&gt;.&lt;br&gt;
code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// square(the first rendered one)
const cubeGeometry = new THREE.BoxGeometry(200, 200, 200)
// square material
const cubeMaterial = new THREE.MeshLambertMaterial({
color: 0x00ff00
})
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
scene.add(cube)
﻿
// cylinder(the next rendered one)
const cyGeometry = new THREE.CylinderGeometry(50, 50, 300, 32)
const cyMaterial = new THREE.MeshLambertMaterial({
color: 0xffff00
})
// cylinder material
const cylinder = new THREE.Mesh(cyGeometry, cyMaterial)
cylinder.rotateX(Math.PI / 2)
scene.add(cylinder)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;﻿&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7323m5v921b3ge6h0nf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7323m5v921b3ge6h0nf.png" alt="Image" width="760" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;﻿&lt;br&gt;
&lt;code&gt;depthTest&lt;/code&gt;: determine whether starting off depth test or not. its essence is calling &lt;code&gt;gl.enable(gl.DEPTH_TEST)&lt;/code&gt;.&lt;br&gt;
for instance, if we want that the cylinder isn't covered by the square, we can set the &lt;code&gt;depthTest&lt;/code&gt; parameter of the cylinder to false:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const cyMaterial = new THREE.MeshLambertMaterial({
...
depthTest: false
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;﻿&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu15nkdb1njb61qzyxfkg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu15nkdb1njb61qzyxfkg.png" alt="Image" width="742" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;﻿&lt;br&gt;
&lt;code&gt;depthWrite&lt;/code&gt;: decide whether the depth buffer can be writable . its essence is calling &lt;code&gt;gl.depthMask( false )&lt;/code&gt;.&lt;br&gt;
and similar to the above, we can set &lt;code&gt;depthWrite&lt;/code&gt; to false for the cylinder so that it isn't covered by the square:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const cubeMaterial = new THREE.MeshLambertMaterial({
...
depthWrite: false
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;﻿&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4y3z3qqnbu81fo87ju7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4y3z3qqnbu81fo87ju7.png" alt="Image" width="748" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;﻿&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Javascript - difference between var, let, and const</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Sat, 21 Dec 2024 07:27:57 +0000</pubDate>
      <link>https://dev.to/handsometan/javascript-difference-between-var-let-and-const-2fhj</link>
      <guid>https://dev.to/handsometan/javascript-difference-between-var-let-and-const-2fhj</guid>
      <description>&lt;p&gt;In the early days, &lt;code&gt;var&lt;/code&gt; keyword is used usually to define a variable, but it would bring some troubles, such as variable obfuscation and memory leaks about variable, firstly, let's learn about variable scope in Javascript:&lt;br&gt;
  there are only global and local scopes in Javscript before ES6 and thease are distinguished by function region. variables defined within a function are local and external variables are global. Variables defined by &lt;code&gt;var&lt;/code&gt; are declared at the top of their scope in advance and assigned the value &lt;code&gt;underfined&lt;/code&gt; regardless of where they are declared. Finally, variable lookup is bottom-up, so variables within a function cannot be accessed by the functions.&lt;br&gt;
﻿&lt;br&gt;
  After ES6, &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; keyword appeared while block scope was introduced. Block scope is differentiated by &lt;code&gt;{  }&lt;/code&gt;, so &lt;code&gt;if, for, while, etc&lt;/code&gt; all have their own block scope, but must use &lt;code&gt;let, const&lt;/code&gt; keyword declared variables and &lt;code&gt;var&lt;/code&gt; hasn't block scope yet. At the same time, &lt;code&gt;let, const&lt;/code&gt; haven't also hoisted-variable as &lt;code&gt;var&lt;/code&gt; do.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>CSS3: linear-gradient and radial-gradient</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Wed, 11 Dec 2024 03:37:27 +0000</pubDate>
      <link>https://dev.to/handsometan/css3-linear-gradient-and-radial-gradient-5773</link>
      <guid>https://dev.to/handsometan/css3-linear-gradient-and-radial-gradient-5773</guid>
      <description>&lt;p&gt;I have used many css3 properties before, but soon forgot about them because many of them are complicated to remember, so I wanna to write blog to make it easier to remember them.&lt;br&gt;
so let me first explain &lt;code&gt;line-gradient&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;background-image: linear-gradient(direction, color-step1, color-step2, ....)&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;direction: using angle to indicate the gradient direction whose values can be an angle or one of them: to left, to right, to top, to bottom. to bottom(180deg) is the default.
﻿&lt;/li&gt;
&lt;li&gt;color-step: the beginning color for gradient, consisting of two parts: color: valid css color value;
length or percentage: the beginning position, not allowing negative value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;examples(assuming height:100px)&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;background:linear-gradient(to bottom, red 0%,yellow 50%,green 100%);&lt;/code&gt; same to &lt;code&gt;background:linear-gradient(180deg, red 0px, yellow 50px, green 100px);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpwalv86sedooem6f192.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpwalv86sedooem6f192.png" alt="linear-gradient illustration" width="243" height="178"&gt;&lt;/a&gt;&lt;br&gt;
﻿&lt;br&gt;
&lt;em&gt;repeatng-linear-gradient()&lt;/em&gt;: &lt;code&gt;background: repeating-linear-gradient(red 0,red 10%,yellow 10%,yellow 20%);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flmjh8w5adxkxxtckrpqm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flmjh8w5adxkxxtckrpqm.png" alt="repeatng-linear-gradient illustration" width="245" height="181"&gt;&lt;/a&gt;&lt;br&gt;
﻿&lt;br&gt;
thease parameters represent 0% - 10% from red to red, 10% - 20% from yellow to yellow, and repeat this effect to cover entire element size.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;radial-gradient()&lt;/strong&gt;&lt;br&gt;
this function parametes consist of five parts: shape, size, the position of circle center, color, color position.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;shape: ellipse(default) or circle;&lt;/li&gt;
&lt;li&gt;size: I prefer to call it as the increassing direction of  radius of radial gradient, with possible values: farthest-corner(default), closest-corner, furthest-side, closest-side.&lt;/li&gt;
&lt;li&gt;position: the center position of the radial gradient, (50%, 50%) is the default;&lt;/li&gt;
&lt;li&gt;color and color position: same to linear-gradient;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flsnzlegetq8tapatndql.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flsnzlegetq8tapatndql.png" alt="the explanation of usage of radial gradient" width="769" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7728np93nw9vwa2g7x7h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7728np93nw9vwa2g7x7h.png" alt="radial gradient illustration" width="246" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;this effect is that the center position is located at (0,0) and gradient radius is equal to element's width;&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;repeating-radial-gradient()&lt;/code&gt; is same to &lt;code&gt;repeating-linear-gradient()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;lastly, there is the compatibility of linear-gradient and radient-gradient(more about that on &lt;a href="https://caniuse.com/?search=linear-gradient" rel="noopener noreferrer"&gt;CanIuse website&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ohhkle0dia8a5stjduo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ohhkle0dia8a5stjduo.png" alt="the illustration of compatibility of linear-gradient and radient-gradient" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>static and dynamic import directive</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Tue, 10 Dec 2024 10:10:20 +0000</pubDate>
      <link>https://dev.to/handsometan/static-and-dynamic-import-directive-59ic</link>
      <guid>https://dev.to/handsometan/static-and-dynamic-import-directive-59ic</guid>
      <description>&lt;p&gt;in Javascript, import directive has two ways for loading external scripts. The first is static import:&lt;code&gt;import { exports.name } from outside.js&lt;/code&gt; that is an async approach, but only in loading phase. It is a sync approach during the execution phase and will block Javascript main thread. Note: static import directive can only be declared at the top level of the module.&lt;br&gt;
The second is dynamic: &lt;code&gt;import(url).then&lt;br&gt;
().catch()&lt;/code&gt; that can be used anywhere you want. &lt;code&gt;import()&lt;/code&gt; function returns a promise so its behavior is same to promise, which is executed in async method.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Create a sphere with evenly distributed points with three.js</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Mon, 02 Dec 2024 03:14:39 +0000</pubDate>
      <link>https://dev.to/handsometan/create-a-sphere-with-evenly-distributed-points-with-threejs-17no</link>
      <guid>https://dev.to/handsometan/create-a-sphere-with-evenly-distributed-points-with-threejs-17no</guid>
      <description>&lt;p&gt;In fact, I have yet to find a way that all points are distributed uniformly. All the methods I have found can only approach a uniform distribution, so  I recommend a simpler method in my opinion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const spherical = new THREE.Spherical();
spherical.radius = 5;
for (let i = 0; i &amp;lt; points; i++) {
﻿
  let phi = Math.acos(1.0 - (2.0 * i + 0.5) / points);
  let theta = Math.PI * (1 + Math.sqrt(5)) * i;
﻿
  spherical.phi = phi; 
  spherical.theta = theta; 
  const x = spherical.radius * Math.sin(spherical.phi) * 
  Math.cos(spherical.theta);
  const y = spherical.radius * Math.sin(spherical.phi) * 
            Math.sin(spherical.theta);
  const z = spherical.radius * Math.cos(spherical.phi);
......
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also don't understand this theoretical principle, because my math is bad, if you are intersting in this principle you can search for relevant information on Stack Overflow.&lt;br&gt;
﻿&lt;br&gt;
﻿&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Instructions on using CSS2(3)DObject with Vue</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Wed, 27 Nov 2024 15:11:23 +0000</pubDate>
      <link>https://dev.to/handsometan/instructions-on-using-css23dobject-with-vue-1gh5</link>
      <guid>https://dev.to/handsometan/instructions-on-using-css23dobject-with-vue-1gh5</guid>
      <description>&lt;p&gt;Today I used CSS2DObject in a Vue project, but css styles didn't work on this CSS2DObject.  After searching for some information, I found this problem is casued by &lt;code&gt;scoped&lt;/code&gt; syntax sugar. Let's review the essence of &lt;code&gt;scoped&lt;/code&gt; syntax sugar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;style scoped&amp;gt;
.className {
...
}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after compilation, the codes above can be displayed as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;style scoped&amp;gt;
.className[data-v-hash] {
...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and all elements in vue component have added data-v-hash attribute, except for elements we created by ourselves, so css styles with  &lt;code&gt;scoped&lt;/code&gt; syntax sugar do not work on these elements.&lt;/p&gt;

</description>
      <category>threejs</category>
      <category>vue</category>
    </item>
    <item>
      <title>Notes on using ref and reactive in Vue</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Tue, 26 Nov 2024 04:08:59 +0000</pubDate>
      <link>https://dev.to/handsometan/notes-on-using-ref-and-reactive-in-vue-3j8h</link>
      <guid>https://dev.to/handsometan/notes-on-using-ref-and-reactive-in-vue-3j8h</guid>
      <description>&lt;p&gt;﻿&lt;br&gt;
today, I used &lt;code&gt;ref&lt;/code&gt; function to get a reference to an element and got a problem that the value of this &lt;code&gt;ref&lt;/code&gt; object is null when using it in &lt;code&gt;onMounted()&lt;/code&gt; function. Then, to solve this problem, I search for &lt;code&gt;ref&lt;/code&gt; on official vue website, but I found a new function: &lt;code&gt;useTemplateRef()&lt;/code&gt; instead of &lt;code&gt;ref&lt;/code&gt;. At this point, I know the vue version has become 3.5+. Vue team has replaced &lt;code&gt;ref&lt;/code&gt; fucntion with &lt;code&gt;useTemplateRef()&lt;/code&gt; to get element references, but when I use this new fucntion in the code &lt;code&gt;ref&lt;/code&gt; function is used, it still doesn't work. After Thinking a lot of time, I finally found the problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
/*** code *** /
........code
﻿
function initThree() {
let container= useTemplateRef('container');
}
﻿
........code
﻿
onMounted(()=&amp;gt;{
container.appendChild(...);
})
/*** code *** /
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this is because the &lt;code&gt;setup&lt;/code&gt; syntactic sugar puzzles me. let's turn back the essence of &lt;code&gt;setup&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script&amp;gt;
/*** code *** /
........code
setup() {
function initThree() {
let container= useTemplateRef('container');
}
return { container };
}
........code
﻿
onMounted(()=&amp;gt;{
container.appendChild(...);
})
/*** code *** /
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;here I defined container variable inside an inner function, so that it cannot be accessed in the top scope of &lt;code&gt;setup()&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>vue</category>
    </item>
    <item>
      <title>Homogeneous and Cartesian coordinates</title>
      <dc:creator>HandsomeTan</dc:creator>
      <pubDate>Sat, 23 Nov 2024 14:20:43 +0000</pubDate>
      <link>https://dev.to/handsometan/homogeneous-coordinate-and-5dl6</link>
      <guid>https://dev.to/handsometan/homogeneous-coordinate-and-5dl6</guid>
      <description>&lt;p&gt;In Computer Graphics, Cartesian coordinate is a common coordinate system, but for matrix calculation to be convenient we introduce Homogeneous coordinate system. The reasons are as below:&lt;br&gt;
  For a example of two-dimensional, assuming the position of a object  is &lt;code&gt;{x, y}&lt;/code&gt; and applying a translation operation to this object to obtain a new position: &lt;code&gt;{x + tx, y + ty}&lt;/code&gt;, which is a manual calculation method. Matrix multiplication is a method used by computers for coordinate transformation, but whether to use tow-dimensional or three-dimensional, multiplication doesn't work on translation operation. So we bring in additional one dimension, whose value is usually 1, so the coordinate of object in two-dimensional is &lt;code&gt;{x, y, w}&lt;/code&gt;. The conversion formula between  homogeneous coordinates&lt;code&gt;({x, y, w})&lt;/code&gt; and Rectangular coordinates&lt;code&gt;({X, Y})&lt;/code&gt; is &lt;code&gt;X = x/w, Y = y/w&lt;/code&gt;, Now we can use translation operation for martix multiplication: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckibjsd7blq1je43xqq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckibjsd7blq1je43xqq3.png" alt="Image description" width="440" height="130"&gt;&lt;/a&gt;&lt;br&gt;
﻿&lt;br&gt;
in this way, all of transform opertions can be finished through matrix multiplication, thereby diminishing computational costs.&lt;br&gt;
  By the way, homogeneous coordinate also address the problem of two parallel lines intersecting. We assume the following situation:&lt;br&gt;
﻿&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj7b8nwpnoenqiuig74m9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj7b8nwpnoenqiuig74m9.png" alt="Image description" width="409" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;this equation have no solution in Euclid space because they are parallel mutually. In Perspective space, we use homogeneous coordinate(x/w, y/w) instead of x,y:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ichmyt9o9pk7i7n5650.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ichmyt9o9pk7i7n5650.png" alt="Image description" width="632" height="114"&gt;&lt;/a&gt;&lt;br&gt;
﻿&lt;br&gt;
there is a solution: (x, y, 0) represents thet intersection of two parallel lines at this point, which represents the position at infinity.&lt;br&gt;
﻿&lt;/p&gt;

</description>
      <category>graphics</category>
      <category>math</category>
    </item>
  </channel>
</rss>
