Skip to content

Instantly share code, notes, and snippets.

@yagudaev
Created August 9, 2022 21:48
Show Gist options
  • Save yagudaev/0c2b89674c6aee8b38cd379752ef58d0 to your computer and use it in GitHub Desktop.
Save yagudaev/0c2b89674c6aee8b38cd379752ef58d0 to your computer and use it in GitHub Desktop.
Figma convert `gradientHandlePositions` to `transformGradient` and vice-versa
import {
convertGradientHandlesToTransform,
convertTransformToGradientHandles
} from "./setPropertyFill"
describe("convertGradientHandlesToTransform", () => {
it("identity matrix", () => {
expect(
convertGradientHandlesToTransform([
{
x: 0,
y: 0.5
},
{
x: 1,
y: 0.5
},
{
x: 0,
y: 1
}
])
).toEqual([
[1, 0, 0],
[0, 1, 0]
])
})
it('scale "up" matrix', () => {
expect(
convertGradientHandlesToTransform([
{
x: 0,
y: 0.25
},
{
x: 0.5,
y: 0.25
},
{
x: 0,
y: 0.5
}
])
).toEqual([
[2, 0, 0],
[0, 2, 0]
])
})
it("complex transform", () => {
expect(
convertGradientHandlesToTransform([
{
x: 0.06041662833364192,
y: 0.9474249294453632
},
{
x: 0.9397033965856045,
y: 0.05248769196422948
},
{
x: 0.5078852470742088,
y: 1.4138814828771724
}
])
).toEqual(
[
[0.5754421949386597, -0.5520178079605103, 0.4882291555404663],
[0.5520178079605103, 0.542364239692688, -0.04720045626163483]
].map((row) => row.map((v) => expect.closeTo(v, 15)))
)
})
})
describe("convertTransformToGradientHandles", () => {
it("identity matrix", () => {
expect(
convertTransformToGradientHandles([
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
])
).toEqual([
{
x: 0,
y: 0.5
},
{
x: 1,
y: 0.5
},
{
x: 0,
y: 1
}
])
})
// TODO: test adds row if missing
it('matrix with scale "up"', () => {
expect(
convertTransformToGradientHandles([
[2, 0, 0],
[0, 2, 0],
[0, 0, 1]
])
).toEqual([
{
x: 0,
y: 0.25
},
{
x: 0.5,
y: 0.25
},
{
x: 0,
y: 0.5
}
])
})
it("complex matrix", () => {
expect(
convertTransformToGradientHandles([
[0.5754421949386597, -0.5520178079605103, 0.4882291555404663],
[0.5520178079605103, 0.542364239692688, -0.04720045626163483],
[0, 0, 1]
])
).toEqual(
[
{
x: 0.06041662833364192,
y: 0.9474249294453632
},
{
x: 0.9397033965856045,
y: 0.05248769196422948
},
{
x: 0.5078852470742088,
y: 1.4138814828771724
}
].map(({ x, y }) => ({ x: expect.closeTo(x, 15), y: expect.closeTo(y, 15) }))
)
})
})
import * as math from "mathjs"
const identityMatrixHandlePositions = [
[0, 1, 0],
[0.5, 0.5, 1],
[1, 1, 1]
]
export function convertGradientHandlesToTransform(
gradientHandlePositions: [
{ x: number; y: number },
{ x: number; y: number },
{ x: number; y: number }
]
) {
const gh = gradientHandlePositions
const d = [
[gh[0].x, gh[1].x, gh[2].x],
[gh[0].y, gh[1].y, gh[2].y],
[1, 1, 1]
]
const o = identityMatrixHandlePositions
const m = math.multiply(o, math.inv(d))
return [m[0], m[1]]
}
export function convertTransformToGradientHandles(transform: number[][]) {
const inverseTransform = math.inv(transform)
// point matrix
const mp = math.multiply(inverseTransform, identityMatrixHandlePositions)
return [
{ x: mp[0][0], y: mp[1][0] },
{ x: mp[0][1], y: mp[1][1] },
{ x: mp[0][2], y: mp[1][2] }
]
}
@urosrakovicdev
Copy link

Hi guys, Im not very good in handling matrix and vectors, maybe you guys can help me. I need to convert figma gradient into css (Opposite to your css->figma plugin), but I have problem calculating gradient angle from 'gradientTransform' matrix from figma's plugin api. I would really appreciate it if someone could help me out with this. :)

@yagudaev
Copy link
Author

yagudaev commented Jun 1, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment