UNPKG

zeplin-extension-style-kit

Version:

Models and utilities to generate CSS-like style code in Zeplin extensions.

84 lines (67 loc) 2.74 kB
import { ColorStop } from "@zeplin/extension-model"; import { ColorNameResolver, ColorParams, StyleValue } from "../../common.js"; import { Percent } from "../percent.js"; import { LinearColorStop } from "./linearColorStop.js"; interface Point { x: number; y: number; } export class RadialGradient implements StyleValue { center: Point; colorStops: LinearColorStop[]; constructor( colorStops: ColorStop[], from: Point, to: Point, width: number, height: number ) { this.center = from; /* * Convert the relative `from` and `to` positions on a layer to absolute positions * by multiplying them with the width and height of the layer */ const x1 = from.x * width; const y1 = from.y * height; const x2 = to.x * width; const y2 = to.y * height; // The length of the gradient line between `from` (center) and `to` points const gradientDistance = Math.hypot(x1 - x2, y1 - y2); let farthestDistance = 0; const corners = [ { x: 0, y: 0 }, { x: width, y: 0 }, { x: width, y: height }, { x: 0, y: height } ]; corners.forEach(corner => { const distance = Math.hypot(x1 - corner.x, y1 - corner.y); if (distance > farthestDistance) { farthestDistance = distance; } }); const distanceRatio = gradientDistance / farthestDistance; this.colorStops = colorStops.map(({ color, position: p }) => { // Convert the position coming from design tool to position on the actual gradient line const position = p * distanceRatio; return new LinearColorStop({ color, position }); }); } valueOf(): string { const { center, colorStops } = this; return `radialGradient::cx:${center.x}:cy:${center.y}:${colorStops.map(cs => cs.valueOf()).join(":")}`; } equals(other: RadialGradient): boolean { return ( this.center.x === other.center.x && this.center.y === other.center.y && this.colorStops.length === other.colorStops.length && this.colorStops.every((stop, i) => stop.equals(other.colorStops[i])) ); } toStyleValue({ colorFormat }: ColorParams, colorNameResolver: ColorNameResolver) { const { center, colorStops } = this; const colorStopStyle = colorStops.map(cs => cs.toStyleValue({ colorFormat }, colorNameResolver)).join(", "); return `radial-gradient(circle at ${new Percent(center.x).toStyleValue()} ${new Percent(center.y).toStyleValue()}, ${colorStopStyle})`; } }