@ray-js/lamp-circle-picker 1.0.12-beta-3 → 1.0.13-beta-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -129,7 +129,7 @@ export default Render({
129
129
  return null;
130
130
  },
131
131
 
132
- drawRingWithConicGradient(params) {
132
+ drawRingWithGradientSegments(params) {
133
133
  let {
134
134
  startAngle,
135
135
  endAngle,
@@ -142,6 +142,7 @@ export default Render({
142
142
  centerX,
143
143
  centerY,
144
144
  ringBorderColor,
145
+ lineCap = 'round',
145
146
  } = params;
146
147
 
147
148
  // 检查 canvas 和 context
@@ -258,13 +259,106 @@ export default Render({
258
259
  ctx.fill();
259
260
  ctx.closePath();
260
261
  }
261
- ctx.globalCompositeOperation = 'destination-out';
262
+
263
+ // 注意:这里不设置 globalCompositeOperation,让调用方决定是否需要
264
+ // 返回渐变颜色数组,供后续绘制端点使用
265
+ return gradientColors;
266
+ },
267
+
268
+ // 绘制圆形端点以模拟 lineCap: 'round' 效果
269
+ drawRoundEndpoints(params) {
270
+ const {
271
+ ctx,
272
+ centerX,
273
+ centerY,
274
+ innerRadius,
275
+ outerRadius,
276
+ startAngle,
277
+ endAngle,
278
+ gradientColors,
279
+ scale,
280
+ } = params;
281
+
282
+ // 计算端点半径(色环宽度的一半)
283
+ const endpointRadius = ((outerRadius - innerRadius) / 2) * scale;
284
+ // 计算色环中线半径
285
+ const midRadius = (innerRadius + (outerRadius - innerRadius) / 2) * scale;
286
+
287
+ // 起始端点(135度位置)
288
+ const startAngleRad = (startAngle * Math.PI) / 180;
289
+ const startX = centerX + midRadius * Math.cos(startAngleRad);
290
+ const startY = centerY + midRadius * Math.sin(startAngleRad);
291
+ const startColor = gradientColors[1] || gradientColors[0]; // 使用第一个颜色
292
+
293
+ // 结束端点(405度位置)
294
+ const endAngleRad = (endAngle * Math.PI) / 180;
295
+ const endX = centerX + midRadius * Math.cos(endAngleRad);
296
+ const endY = centerY + midRadius * Math.sin(endAngleRad);
297
+ const endColor =
298
+ gradientColors[gradientColors.length - 2] || gradientColors[gradientColors.length - 1]; // 使用最后一个颜色
299
+
300
+ // 重置合成操作以正常绘制端点
301
+ ctx.globalCompositeOperation = 'source-over';
302
+
303
+ // 起始端点 - 使用半圆,封闭色环起点
304
+ // 半圆应该朝向色环外侧(逆时针方向),角度范围是从色环切线的外侧到内侧
305
+ const startHalfCircleStart = startAngleRad - Math.PI; // 色环外侧
306
+ const startHalfCircleEnd = startAngleRad; // 色环内侧
307
+
308
+ ctx.beginPath();
309
+ ctx.arc(startX, startY, endpointRadius, startHalfCircleStart, startHalfCircleEnd, false);
310
+
311
+ // 使用与色环相同的径向渐变
312
+ const startGradient = ctx.createRadialGradient(
313
+ centerX,
314
+ centerY,
315
+ innerRadius * scale,
316
+ centerX,
317
+ centerY,
318
+ outerRadius * scale
319
+ );
320
+ startGradient.addColorStop(0, startColor);
321
+ startGradient.addColorStop(1, startColor);
322
+
323
+ ctx.fillStyle = startGradient;
324
+ ctx.fill();
325
+ ctx.closePath();
326
+
327
+ // 结束端点 - 使用半圆,封闭色环终点
328
+ // 半圆应该朝向色环外侧(顺时针方向),角度范围是从色环切线的内侧到外侧
329
+ const endHalfCircleStart = endAngleRad; // 色环内侧
330
+ const endHalfCircleEnd = endAngleRad + Math.PI; // 色环外侧
331
+
332
+ ctx.beginPath();
333
+ ctx.arc(endX, endY, endpointRadius, endHalfCircleStart, endHalfCircleEnd, false);
334
+
335
+ // 使用与色环相同的径向渐变
336
+ const endGradient = ctx.createRadialGradient(
337
+ centerX,
338
+ centerY,
339
+ innerRadius * scale,
340
+ centerX,
341
+ centerY,
342
+ outerRadius * scale
343
+ );
344
+ endGradient.addColorStop(0, endColor);
345
+ endGradient.addColorStop(1, endColor);
346
+
347
+ ctx.fillStyle = endGradient;
348
+ ctx.fill();
349
+ ctx.closePath();
262
350
  },
263
351
 
264
352
  // 环形色盘 降级绘制
265
353
  async renderAnnulusColorLowRank(id, radius, innerRingRadius, options = {}) {
266
354
  let canvas = null;
267
- const { touchCircleStrokeStyle, ringBorderColor, inactive, maskVisible } = options;
355
+ const {
356
+ touchCircleStrokeStyle,
357
+ ringBorderColor,
358
+ inactive,
359
+ maskVisible,
360
+ lineCap = 'round',
361
+ } = options;
268
362
  this.touchCircleStrokeStyle = touchCircleStrokeStyle;
269
363
  this.inactive = inactive;
270
364
  this.maskVisible = maskVisible;
@@ -300,7 +394,10 @@ export default Render({
300
394
  const offsetDegree = 270;
301
395
  const endDegree = startDegree + offsetDegree;
302
396
 
303
- this.drawRingWithConicGradient({
397
+ // 保存 canvas 状态(在绘制主色环之前)
398
+ ctx.save();
399
+
400
+ const gradientColors = this.drawRingWithGradientSegments({
304
401
  startAngle: startDegree,
305
402
  endAngle: endDegree,
306
403
  offsetDegree,
@@ -312,17 +409,35 @@ export default Render({
312
409
  centerX: poxCenterX,
313
410
  centerY: poxCenterY,
314
411
  ringBorderColor,
412
+ lineCap,
315
413
  });
316
414
 
415
+ // 恢复 canvas 状态(移除裁剪区域)
416
+ ctx.restore();
417
+
418
+ // 绘制圆形端点(在没有裁剪区域限制的情况下)
419
+ if (lineCap === 'round' && gradientColors && gradientColors.length > 0) {
420
+ this.drawRoundEndpoints({
421
+ ctx,
422
+ centerX: poxCenterX,
423
+ centerY: poxCenterY,
424
+ innerRadius: innerRingRadius,
425
+ outerRadius: radius,
426
+ startAngle: startDegree,
427
+ endAngle: endDegree,
428
+ gradientColors,
429
+ scale: scale, // 使用原始 scale
430
+ });
431
+ }
432
+
317
433
  ctx.scale(scale, scale);
318
434
  canvas.style.width = `${diameter}px`;
319
435
  canvas.style.height = `${diameter}px`;
320
436
  this.annulusContext = ctx;
321
437
  },
322
438
 
323
- // 环形色盘
439
+ // 环形色盘 - 统一使用降级渲染
324
440
  async renderAnnulusColor(id, radius, innerRingRadius, temp = 0, options = {}) {
325
- let canvas = null;
326
441
  const {
327
442
  touchCircleStrokeStyle = '',
328
443
  touchCircleLineWidth = 0,
@@ -331,70 +446,19 @@ export default Render({
331
446
  inactive = false,
332
447
  maskVisible = false,
333
448
  } = options || {};
449
+
450
+ // 设置实例属性
334
451
  this.touchCircleStrokeStyle = touchCircleStrokeStyle;
335
452
  this.touchCircleLineWidth = touchCircleLineWidth;
336
453
  this.hideThumb = hideThumb;
337
454
  this.inactive = inactive;
338
455
  this.maskVisible = maskVisible;
339
- try {
340
- canvas = await getCanvasById(id);
341
- } catch (error) {
342
- console.error(error);
343
- return;
344
- }
345
- if (!canvas) {
346
- console.error('canvas not found');
347
- return;
348
- }
456
+
349
457
  const { useEventChannel, eventChannelName } = options || {};
350
458
  this.useEventChannel = useEventChannel;
351
459
  this.eventChannelName = eventChannelName;
352
- canvas.width = radius * 4;
353
- canvas.height = radius * 4;
354
- const ctx = canvas.getContext('2d');
355
-
356
- const startAngle = Math.PI * 0.75;
357
- const endAngle = Math.PI * 0.25;
358
- const counterclockwise = false;
359
- ctx.beginPath();
360
- ctx.arc(
361
- radius * 2,
362
- radius * 2,
363
- innerRingRadius * 2 + (radius - innerRingRadius),
364
- startAngle,
365
- endAngle,
366
- counterclockwise
367
- );
368
-
369
- let grd = null;
370
- if (ctx.createConicGradient && lineCap === 'round') {
371
- try {
372
- grd = ctx.createConicGradient(startAngle - Math.PI * 0.1, radius * 2, radius * 2);
373
- options.colorList?.forEach(item => {
374
- grd.addColorStop(item.offset, item.color);
375
- });
376
- //设定曲线粗细度
377
- ctx.lineWidth = (radius - innerRingRadius) * 2;
378
- //给曲线着色
379
- ctx.strokeStyle = grd;
380
- //连接处样式
381
- ctx.lineCap = lineCap || 'round';
382
- //给环着色
383
- ctx.stroke();
384
- ctx.closePath();
385
- ctx.scale(2, 2);
386
- canvas.style.width = `${radius * 2}px`;
387
- canvas.style.height = `${radius * 2}px`;
388
- this.annulusContext = ctx;
389
- } catch (err) {
390
- console.error('createConicGradient:', err);
391
- }
392
- !this.hideThumb && this.renderAnnulusColorThumb(id, temp);
393
- this.callMethod('initedCanvas', {});
394
- return;
395
- }
396
460
 
397
- // 降级渲染,兼容安卓低版本机型
461
+ // 统一使用降级渲染,确保所有机型的一致性
398
462
  this.renderAnnulusColorLowRank(id, radius, innerRingRadius, options);
399
463
 
400
464
  !this.hideThumb && this.renderAnnulusColorThumb(id, temp);
@@ -446,7 +510,7 @@ export default Render({
446
510
  this.radius +
447
511
  (this.innerRingRadius + (this.radius - this.innerRingRadius) / 2) *
448
512
  Math.sin((angle * Math.PI) / 180);
449
- const { data } = ctx.getImageData(x * 2, y * 2, 1, 1);
513
+ const { data } = ctx.getImageData(Math.round(x * 2), Math.round(y * 2), 1, 1);
450
514
  const rgb = { r: data[0], g: data[1], b: data[2] };
451
515
  this.updateThumbPosition(x, y, rgb);
452
516
  const emitRes = {
@@ -507,7 +571,7 @@ export default Render({
507
571
  console.error('ctx not found');
508
572
  return;
509
573
  }
510
- const { data } = ctx.getImageData(x * 2, y * 2, 1, 1);
574
+ const { data } = ctx.getImageData(Math.round(x * 2), Math.round(y * 2), 1, 1);
511
575
  const r = data[0];
512
576
  const g = data[1];
513
577
  const b = data[2];
@@ -21,7 +21,7 @@
21
21
  border-radius: 50%;
22
22
  border: 5rpx solid rgba(255, 255, 255, 0.8);
23
23
  z-index: 99;
24
- box-shadow:0 0 7px 0 rgba(0, 0, 0, 0.16);
24
+ box-shadow: 0 0 7px 0 rgba(0, 0, 0, 0.16);
25
25
  }
26
26
 
27
27
  .colorTipWrapper {
package/lib/hooks.js CHANGED
@@ -8,8 +8,6 @@ import { getSystemCacheInfo } from './utils';
8
8
  */
9
9
  export const useStdPx2Adapt = function (stdPx) {
10
10
  let toFixed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
11
- const {
12
- screenWidth
13
- } = useMemo(() => getSystemCacheInfo(), [stdPx]);
14
- return +(stdPx * (screenWidth / 375)).toFixed(toFixed) || stdPx;
11
+ const systemInfo = useMemo(() => getSystemCacheInfo(), [stdPx]);
12
+ return +(stdPx * (systemInfo.windowWidth / 375)).toFixed(toFixed) || stdPx;
15
13
  };
@@ -6,7 +6,7 @@ type HSL = {
6
6
  };
7
7
  declare const rgbToHsl: (r: number, g: number, b: number) => HSL;
8
8
  export declare const getSystemCacheInfo: () => {
9
- screenWidth: number;
10
- screenHeight: number;
9
+ windowWidth: number;
10
+ windowHeight: number;
11
11
  };
12
12
  export { rgbToHsl, rgb2hsv, hsv2rgb };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/lamp-circle-picker",
3
- "version": "1.0.12-beta-3",
3
+ "version": "1.0.13-beta-1",
4
4
  "description": "照明缺角色环",
5
5
  "main": "lib/index",
6
6
  "files": [