mirror of
https://github.com/idrawjs/idraw
synced 2026-05-23 17:48:23 +00:00
feat: rename gradient type and improve opacity logic
This commit is contained in:
parent
3f9dca1353
commit
9bf2403c6d
10 changed files with 79 additions and 29 deletions
|
|
@ -23,7 +23,8 @@
|
|||
"devDependencies": {
|
||||
"@idraw/types": "^0.4.0-alpha.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dependencies": {},
|
||||
"peerDependencies": {
|
||||
"@idraw/util": "^0.4.0-alpha.3",
|
||||
"@idraw/renderer": "^0.4.0-alpha.3"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@
|
|||
"devDependencies": {
|
||||
"@idraw/types": "^0.4.0-alpha.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dependencies": {},
|
||||
"peerDependencies": {
|
||||
"@idraw/board": "^0.4.0-alpha.3",
|
||||
"@idraw/renderer": "^0.4.0-alpha.3",
|
||||
"@idraw/util": "^0.4.0-alpha.3"
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@
|
|||
"devDependencies": {
|
||||
"@idraw/types": "^0.4.0-alpha.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dependencies": {},
|
||||
"peerDependencies": {
|
||||
"@idraw/util": "^0.4.0-alpha.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
|
|
|||
|
|
@ -14,11 +14,6 @@ export function drawBox(
|
|||
viewSizeInfo: ViewSizeInfo;
|
||||
}
|
||||
): void {
|
||||
if (viewElem?.detail?.opacity !== undefined && viewElem?.detail?.opacity > 0) {
|
||||
ctx.globalAlpha = viewElem.detail.opacity;
|
||||
} else {
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
const { pattern, renderContent, originElem, calcElemSize, viewScaleInfo, viewSizeInfo } = opts || {};
|
||||
|
||||
drawClipPath(ctx, viewElem, {
|
||||
|
|
@ -27,14 +22,19 @@ export function drawBox(
|
|||
viewScaleInfo,
|
||||
viewSizeInfo,
|
||||
renderContent: () => {
|
||||
if (viewElem?.detail?.opacity !== undefined && viewElem?.detail?.opacity >= 0) {
|
||||
ctx.globalAlpha = viewElem.detail.opacity;
|
||||
} else {
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
drawBoxBackground(ctx, viewElem, { pattern, viewScaleInfo, viewSizeInfo });
|
||||
renderContent?.();
|
||||
drawBoxBorder(ctx, viewElem, { viewScaleInfo, viewSizeInfo });
|
||||
// TODO
|
||||
// drawBoxBackground(ctx, viewElem, { pattern, viewScaleInfo, viewSizeInfo });
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
});
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
|
||||
function drawClipPath(
|
||||
|
|
@ -141,16 +141,18 @@ function drawBoxBackground(
|
|||
ctx.fillStyle = pattern as CanvasPattern;
|
||||
} else if (typeof viewElem.detail.background === 'string') {
|
||||
ctx.fillStyle = viewElem.detail.background;
|
||||
} else if (viewElem.detail.background?.type === 'linearGradient') {
|
||||
} else if (viewElem.detail.background?.type === 'linear-gradient') {
|
||||
const colorStyle = createColorStyle(ctx, viewElem.detail.background, {
|
||||
viewElementSize: { x, y, w, h },
|
||||
viewScaleInfo
|
||||
viewScaleInfo,
|
||||
opacity: ctx.globalAlpha
|
||||
});
|
||||
ctx.fillStyle = colorStyle;
|
||||
} else if (viewElem.detail.background?.type === 'radialGradient') {
|
||||
} else if (viewElem.detail.background?.type === 'radial-gradient') {
|
||||
const colorStyle = createColorStyle(ctx, viewElem.detail.background, {
|
||||
viewElementSize: { x, y, w, h },
|
||||
viewScaleInfo
|
||||
viewScaleInfo,
|
||||
opacity: ctx.globalAlpha
|
||||
});
|
||||
ctx.fillStyle = colorStyle;
|
||||
if (transform && transform.length > 0) {
|
||||
|
|
@ -190,6 +192,11 @@ function drawBoxBorder(ctx: ViewContext2D, viewElem: Element<ElementType>, opts:
|
|||
if (!isColorStr(viewElem.detail.borderColor)) {
|
||||
return;
|
||||
}
|
||||
if (viewElem?.detail?.opacity !== undefined && viewElem?.detail?.opacity >= 0) {
|
||||
ctx.globalAlpha = viewElem.detail.opacity;
|
||||
} else {
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
const { viewScaleInfo } = opts;
|
||||
const { scale } = viewScaleInfo;
|
||||
let borderColor = '#000000';
|
||||
|
|
@ -309,6 +316,7 @@ function drawBoxBorder(ctx: ViewContext2D, viewElem: Element<ElementType>, opts:
|
|||
ctx.arcTo(x, y, x + w, y, radiusList[0]);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,12 @@ export function drawCircle(ctx: ViewContext2D, elem: Element<'circle'>, opts: Re
|
|||
const centerX = x + a;
|
||||
const centerY = y + b;
|
||||
|
||||
if (elem?.detail?.opacity !== undefined && elem?.detail?.opacity >= 0) {
|
||||
ctx.globalAlpha = elem.detail.opacity;
|
||||
} else {
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
|
||||
// draw border
|
||||
if (typeof borderWidth === 'number' && borderWidth > 0) {
|
||||
const ba = borderWidth / 2 + a;
|
||||
|
|
@ -30,11 +36,13 @@ export function drawCircle(ctx: ViewContext2D, elem: Element<'circle'>, opts: Re
|
|||
ctx.beginPath();
|
||||
const fillStyle = createColorStyle(ctx, background, {
|
||||
viewElementSize: { x, y, w, h },
|
||||
viewScaleInfo
|
||||
viewScaleInfo,
|
||||
opacity: ctx.globalAlpha
|
||||
});
|
||||
ctx.fillStyle = fillStyle;
|
||||
ctx.circle(centerX, centerY, a, b, 0, 0, 2 * Math.PI);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
ctx.globalAlpha = 1;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { ViewContext2D, ViewScaleInfo, ElementSize, LinearGradientColor, RadialGradientColor } from '@idraw/types';
|
||||
import { mergeHexColorAlpha } from '@idraw/util';
|
||||
|
||||
export function createColorStyle(
|
||||
ctx: ViewContext2D,
|
||||
|
|
@ -6,15 +7,16 @@ export function createColorStyle(
|
|||
opts: {
|
||||
viewElementSize: ElementSize;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
opacity: number;
|
||||
}
|
||||
): string | CanvasPattern | CanvasGradient {
|
||||
if (typeof color === 'string') {
|
||||
return color;
|
||||
}
|
||||
const { viewElementSize, viewScaleInfo } = opts;
|
||||
const { viewElementSize, viewScaleInfo, opacity = 1 } = opts;
|
||||
const { x, y } = viewElementSize;
|
||||
const { scale } = viewScaleInfo;
|
||||
if (color?.type === 'linearGradient') {
|
||||
if (color?.type === 'linear-gradient') {
|
||||
const { start, end, stops } = color;
|
||||
const viewStart = {
|
||||
x: x + start.x * scale,
|
||||
|
|
@ -27,12 +29,12 @@ export function createColorStyle(
|
|||
|
||||
const linearGradient = ctx.createLinearGradient(viewStart.x, viewStart.y, viewEnd.x, viewEnd.y);
|
||||
stops.forEach((stop) => {
|
||||
linearGradient.addColorStop(stop.offset, stop.color);
|
||||
linearGradient.addColorStop(stop.offset, mergeHexColorAlpha(stop.color, opacity));
|
||||
});
|
||||
return linearGradient;
|
||||
}
|
||||
|
||||
if (color?.type === 'radialGradient') {
|
||||
if (color?.type === 'radial-gradient') {
|
||||
const { inner, outer, stops } = color;
|
||||
const viewInner = {
|
||||
x: x + inner.x * scale,
|
||||
|
|
@ -46,7 +48,7 @@ export function createColorStyle(
|
|||
};
|
||||
const radialGradient = ctx.createRadialGradient(viewInner.x, viewInner.y, viewInner.radius, viewOuter.x, viewOuter.y, viewOuter.radius);
|
||||
stops.forEach((stop) => {
|
||||
radialGradient.addColorStop(stop.offset, stop.color);
|
||||
radialGradient.addColorStop(stop.offset, mergeHexColorAlpha(stop.color, opacity));
|
||||
});
|
||||
return radialGradient;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export interface GradientStop {
|
|||
}
|
||||
|
||||
export interface LinearGradientColor {
|
||||
type: 'linearGradient';
|
||||
type: 'linear-gradient';
|
||||
start: PointSize;
|
||||
end: PointSize;
|
||||
stops: Array<GradientStop>;
|
||||
|
|
@ -61,7 +61,7 @@ type GadialCircle = PointSize & {
|
|||
};
|
||||
|
||||
export interface RadialGradientColor {
|
||||
type: 'radialGradient';
|
||||
type: 'radial-gradient';
|
||||
inner: GadialCircle;
|
||||
outer: GadialCircle;
|
||||
stops: Array<GradientStop>;
|
||||
|
|
@ -79,7 +79,7 @@ export interface ElementBaseDetail {
|
|||
shadowOffsetX?: number;
|
||||
shadowOffsetY?: number;
|
||||
shadowBlur?: number;
|
||||
color?: string;
|
||||
// color?: string;
|
||||
background?: string | LinearGradientColor | RadialGradientColor;
|
||||
opacity?: number;
|
||||
clipPath?: ElementClipPath;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export { delay, compose, throttle } from './lib/time';
|
||||
export { downloadImageFromCanvas } from './lib/file';
|
||||
export { toColorHexStr, toColorHexNum, isColorStr, colorNameToHex, colorToCSS, colorToLinearGradientCSS } from './lib/color';
|
||||
export { toColorHexStr, toColorHexNum, isColorStr, colorNameToHex, colorToCSS, colorToLinearGradientCSS, mergeHexColorAlpha } from './lib/color';
|
||||
export { createUUID, isAssetId, createAssetId } from './lib/uuid';
|
||||
export { deepClone, sortDataAsserts } from './lib/data';
|
||||
export { istype } from './lib/istype';
|
||||
|
|
@ -33,7 +33,8 @@ export {
|
|||
findElementFromList,
|
||||
findElementsFromList,
|
||||
updateElementInList,
|
||||
getGroupQueueFromList
|
||||
getGroupQueueFromList,
|
||||
getElementSize
|
||||
} from './lib/element';
|
||||
export { checkRectIntersect } from './lib/rect';
|
||||
export {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import type { LinearGradientColor, RadialGradientColor } from '@idraw/types';
|
||||
import { matrixToRadian } from '@idraw/util';
|
||||
|
||||
export function toColorHexNum(color: string): number {
|
||||
return parseInt(color.replace(/^\#/, '0x'));
|
||||
|
|
@ -171,12 +170,12 @@ export function colorToCSS(color?: string | LinearGradientColor | RadialGradient
|
|||
let css = 'transparent';
|
||||
if (typeof color === 'string') {
|
||||
css = color;
|
||||
} else if (color?.type === 'linearGradient') {
|
||||
} else if (color?.type === 'linear-gradient') {
|
||||
const items: string[] = [];
|
||||
if (typeof color.angle === 'number') {
|
||||
items.push(`${color.angle}deg`);
|
||||
} else {
|
||||
items.push(`0deg`);
|
||||
items.push(`180deg`);
|
||||
}
|
||||
if (Array.isArray(color.stops)) {
|
||||
color.stops.forEach((stop) => {
|
||||
|
|
@ -184,7 +183,7 @@ export function colorToCSS(color?: string | LinearGradientColor | RadialGradient
|
|||
});
|
||||
}
|
||||
css = `linear-gradient(${items.join(', ')})`;
|
||||
} else if (color?.type === 'radialGradient') {
|
||||
} else if (color?.type === 'radial-gradient') {
|
||||
const items: string[] = [];
|
||||
if (Array.isArray(color.stops)) {
|
||||
color.stops.forEach((stop) => {
|
||||
|
|
@ -200,7 +199,7 @@ export function colorToLinearGradientCSS(color?: string | LinearGradientColor |
|
|||
let css = 'transparent';
|
||||
if (typeof color === 'string') {
|
||||
css = color;
|
||||
} else if (color?.type === 'radialGradient' || color?.type === 'linearGradient') {
|
||||
} else if (color?.type === 'radial-gradient' || color?.type === 'linear-gradient') {
|
||||
const items: string[] = [];
|
||||
if (Array.isArray(color.stops) && color.stops.length > 0) {
|
||||
color.stops.forEach((stop, i) => {
|
||||
|
|
@ -214,3 +213,26 @@ export function colorToLinearGradientCSS(color?: string | LinearGradientColor |
|
|||
}
|
||||
return css;
|
||||
}
|
||||
|
||||
// alpha [0, 1]
|
||||
export function mergeHexColorAlpha(hex: string, alpha: number): string {
|
||||
if (alpha === 1) {
|
||||
return hex;
|
||||
}
|
||||
let hexAlpha = 1;
|
||||
const regHex1 = /^\#[0-9a-f]{6,6}$/i;
|
||||
const regHex2 = /^\#[0-9a-f]{8,8}$/i;
|
||||
let result = hex;
|
||||
if (regHex1.test(hex)) {
|
||||
hexAlpha = parseInt(hex.substring(5, 7).replace(/^\#/, '0x'));
|
||||
} else if (regHex2.test(hex)) {
|
||||
hexAlpha = parseInt(hex.substring(7, 9).replace(/^\#/, '0x'));
|
||||
result = hex.substring(0, 7);
|
||||
}
|
||||
hexAlpha = hexAlpha * alpha;
|
||||
if (regHex1.test(result) && hexAlpha > 0 && hexAlpha < 1) {
|
||||
const aHexNum = Math.max(0, Math.min(255, Math.ceil(hexAlpha * 256)));
|
||||
result = `${result.toUpperCase()}${aHexNum.toString(16).toUpperCase()}`;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -344,3 +344,9 @@ export function updateElementInList(
|
|||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
export function getElementSize(elem: Element): ElementSize {
|
||||
const { x, y, w, h, angle } = elem;
|
||||
const size: ElementSize = { x, y, w, h, angle };
|
||||
return size;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue