@ray-js/lamp-circle-picker 1.0.15-beta.1 → 1.0.16-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.
@@ -1,4 +1,8 @@
1
1
  import Render from './index.rjs';
2
+ function getArcTopPadding(radius, innerRingRadius) {
3
+ let touchCircleLineWidth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
4
+ return Math.ceil(4 + (innerRingRadius + (radius - innerRingRadius) / 2) + (radius - innerRingRadius - 4) / 2 + (touchCircleLineWidth || 24) / 2 + 4 - radius);
5
+ }
2
6
  const ETipRectPosition = {
3
7
  LEFT: 'LEFT',
4
8
  RIGHT: 'RIGHT'
@@ -68,7 +72,9 @@ Component({
68
72
  colorText: '',
69
73
  tipRectPosition: ETipRectPosition.LEFT,
70
74
  prePowerOff: false,
71
- preShowMask: false
75
+ preShowMask: false,
76
+ topPadding: 0,
77
+ canvasHeight: 200
72
78
  },
73
79
  observers: {
74
80
  'value.**'(v) {
@@ -108,9 +114,11 @@ Component({
108
114
  this.render = new Render(this);
109
115
  const {
110
116
  radius,
111
- innerRingRadius
117
+ innerRingRadius,
118
+ touchCircleLineWidth = 0
112
119
  } = this.data;
113
120
  this.render._setCircles(radius, innerRingRadius);
121
+ this._updateLayoutMetrics(radius, innerRingRadius, touchCircleLineWidth);
114
122
  },
115
123
  ready() {
116
124
  const {
@@ -152,6 +160,7 @@ Component({
152
160
  } = this.data;
153
161
  this.prePowerOff = inactive;
154
162
  this.preShowMask = maskVisible;
163
+ this._updateLayoutMetrics(radius, innerRingRadius, touchCircleLineWidth);
155
164
  // 防止重复渲染
156
165
  if (this.lastValue === value) {
157
166
  return;
@@ -204,11 +213,21 @@ Component({
204
213
  rgb
205
214
  });
206
215
  },
216
+ _updateLayoutMetrics(radius, innerRingRadius) {
217
+ let touchCircleLineWidth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
218
+ const topPadding = getArcTopPadding(radius, innerRingRadius, touchCircleLineWidth);
219
+ this.setData({
220
+ topPadding,
221
+ canvasHeight: radius * 2 + topPadding,
222
+ centerY: radius + topPadding
223
+ });
224
+ },
207
225
  _getLengthByAnglePosition(x, y) {
208
226
  const {
209
- radius
227
+ radius,
228
+ centerY
210
229
  } = this.data;
211
- var radian = Math.atan2(y - radius, x - radius); // 弧度
230
+ var radian = Math.atan2(y - centerY, x - radius); // 弧度
212
231
  var angle = radian * (180 / Math.PI); // 角度
213
232
  let angleData = 0;
214
233
  if (+angle > 135 && +angle <= 180) {
@@ -1,6 +1,17 @@
1
1
  // commonColor.rjs
2
2
  const scale = 2;
3
3
 
4
+ function getArcTopPadding(radius, innerRingRadius, touchCircleLineWidth = 0) {
5
+ const midRadius = innerRingRadius + (radius - innerRingRadius) / 2;
6
+ const thumbDisplayRadius = (radius - innerRingRadius - 4) / 2;
7
+ const shadowDisplay = (touchCircleLineWidth || 24) / 2;
8
+ const strokeHalf = 4;
9
+ const margin = 4;
10
+ return Math.ceil(
11
+ margin + midRadius + thumbDisplayRadius + shadowDisplay + strokeHalf - radius
12
+ );
13
+ }
14
+
4
15
  function reverseColorStops(colorStops) {
5
16
  if (!Array.isArray(colorStops)) {
6
17
  console.error('【ray-circle-picker=> Input parameter must be an array.');
@@ -398,13 +409,19 @@ export default Render({
398
409
  this.radius = radius;
399
410
  this.innerRingRadius = innerRingRadius;
400
411
 
412
+ const { touchCircleLineWidth = 0 } = options;
413
+ this.topPadding = getArcTopPadding(radius, innerRingRadius, touchCircleLineWidth);
414
+ this.centerY = radius + this.topPadding;
415
+ this.centerX = radius;
416
+
401
417
  const diameter = radius * 2;
418
+ const canvasHeight = diameter + this.topPadding;
402
419
  canvas.width = diameter * scale;
403
- canvas.height = diameter * scale;
420
+ canvas.height = canvasHeight * scale;
404
421
  const ctx = canvas.getContext('2d');
405
422
 
406
- const poxCenterX = radius * scale;
407
- const poxCenterY = radius * scale;
423
+ const poxCenterX = this.centerX * scale;
424
+ const poxCenterY = this.centerY * scale;
408
425
 
409
426
  const colorList = options.colorList.map(item => {
410
427
  return {
@@ -454,7 +471,7 @@ export default Render({
454
471
 
455
472
  ctx.scale(scale, scale);
456
473
  canvas.style.width = `${diameter}px`;
457
- canvas.style.height = `${diameter}px`;
474
+ canvas.style.height = `${canvasHeight}px`;
458
475
  this.annulusContext = ctx;
459
476
  },
460
477
 
@@ -515,6 +532,7 @@ export default Render({
515
532
  _setCircles(radius, innerRingRadius) {
516
533
  this.radius = radius;
517
534
  this.innerRingRadius = innerRingRadius;
535
+ this.centerX = radius;
518
536
  },
519
537
  _getAnglePositionByValue(value) {
520
538
  const ctx = this.annulusContext;
@@ -524,14 +542,9 @@ export default Render({
524
542
  }
525
543
 
526
544
  const angle = 135 + (value / 1000) * 270;
527
- const x =
528
- this.radius +
529
- (this.innerRingRadius + (this.radius - this.innerRingRadius) / 2) *
530
- Math.cos((angle * Math.PI) / 180);
531
- const y =
532
- this.radius +
533
- (this.innerRingRadius + (this.radius - this.innerRingRadius) / 2) *
534
- Math.sin((angle * Math.PI) / 180);
545
+ const midRadius = this.innerRingRadius + (this.radius - this.innerRingRadius) / 2;
546
+ const x = this.centerX + midRadius * Math.cos((angle * Math.PI) / 180);
547
+ const y = this.centerY + midRadius * Math.sin((angle * Math.PI) / 180);
535
548
  const { data } = ctx.getImageData(Math.round(x * 2), Math.round(y * 2), 1, 1);
536
549
  const rgb = { r: data[0], g: data[1], b: data[2] };
537
550
  this.updateThumbPosition(x, y, rgb);
@@ -560,8 +573,9 @@ export default Render({
560
573
  this.preRgb = rgb;
561
574
  }
562
575
  let ctx = this.canvasThumbCtx;
576
+ const canvasHeight = this.radius * 2 + (this.topPadding || 0);
563
577
  this.canvasThumb.width = this.radius * 4;
564
- this.canvasThumb.height = this.radius * 4;
578
+ this.canvasThumb.height = canvasHeight * 2;
565
579
  ctx.clearRect(0, 0, this.canvasThumb.width, this.canvasThumb.height);
566
580
  ctx.beginPath();
567
581
  const radius = this.radius - this.innerRingRadius - 4; // 圆弧半径
@@ -585,7 +599,7 @@ export default Render({
585
599
  ctx.stroke();
586
600
  ctx.scale(2, 2);
587
601
  this.canvasThumb.style.width = `${this.radius * 2}px`;
588
- this.canvasThumb.style.height = `${this.radius * 2}px`;
602
+ this.canvasThumb.style.height = `${canvasHeight}px`;
589
603
  },
590
604
  getAnnulusImageData(x, y) {
591
605
  const ctx = this.annulusContext;
@@ -621,10 +635,12 @@ export default Render({
621
635
  },
622
636
  _getValidMaxMinRes(x, y) {
623
637
  const { radius, innerRingRadius } = this;
624
- const xDistance = Math.abs(x - radius);
625
- const yDistance = Math.abs(y - radius);
638
+ const centerX = this.centerX ?? radius;
639
+ const centerY = this.centerY ?? radius;
640
+ const xDistance = Math.abs(x - centerX);
641
+ const yDistance = Math.abs(y - centerY);
626
642
  const distance = Math.sqrt(xDistance * xDistance + yDistance * yDistance);
627
- const radian = Math.atan2(y - radius, x - radius);
643
+ const radian = Math.atan2(y - centerY, x - centerX);
628
644
  let angle = radian * (180 / Math.PI);
629
645
 
630
646
  const mid = 90
@@ -635,39 +651,23 @@ export default Render({
635
651
  angle = 135;
636
652
  }
637
653
 
654
+ const midRadius = innerRingRadius + (radius - innerRingRadius) / 2;
655
+
638
656
  if (angle < 45 || angle > 135) {
639
- const thumbPositionY =
640
- radius +
641
- (innerRingRadius + (radius - innerRingRadius) / 2) *
642
- Math.sin(Math.atan2(y - radius, x - radius));
643
- const thumbPositionX =
644
- radius +
645
- (innerRingRadius + (radius - innerRingRadius) / 2) *
646
- Math.cos(Math.atan2(y - radius, x - radius));
657
+ const thumbPositionY = centerY + midRadius * Math.sin(Math.atan2(y - centerY, x - centerX));
658
+ const thumbPositionX = centerX + midRadius * Math.cos(Math.atan2(y - centerY, x - centerX));
647
659
  return { x: thumbPositionX, y: thumbPositionY };
648
660
  }
649
661
  if (angle >= 45 && angle < 80) {
650
- const thumbPositionY =
651
- radius +
652
- (innerRingRadius + (radius - innerRingRadius) / 2) *
653
- Math.sin(Math.atan2(210 - radius, 210 - radius));
654
- const thumbPositionX =
655
- radius +
656
- (innerRingRadius + (radius - innerRingRadius) / 2) *
657
- Math.cos(Math.atan2(210 - radius, 210 - radius));
662
+ const endpointRadian = (45 * Math.PI) / 180;
663
+ const thumbPositionY = centerY + midRadius * Math.sin(endpointRadian);
664
+ const thumbPositionX = centerX + midRadius * Math.cos(endpointRadian);
658
665
  return { x: thumbPositionX, y: thumbPositionY };
659
666
  }
660
667
  if (angle > 115 && angle <= 135) {
661
- // 修正在范围外的点击区域导致的取色问题
662
- const _angle = 135;
663
- const realAngle = ((180 - _angle) / 180) * Math.PI;
664
-
665
- const thumbPositionY =
666
- radius + (innerRingRadius + (radius - innerRingRadius) / 2) * Math.sin(realAngle);
667
-
668
- const thumbPositionX =
669
- radius - (innerRingRadius + (radius - innerRingRadius) / 2) * Math.cos(realAngle);
670
-
668
+ const endpointRadian = (135 * Math.PI) / 180;
669
+ const thumbPositionY = centerY + midRadius * Math.sin(endpointRadian);
670
+ const thumbPositionX = centerX + midRadius * Math.cos(endpointRadian);
671
671
  return { x: thumbPositionX, y: thumbPositionY };
672
672
  }
673
673
  },
@@ -4,14 +4,14 @@
4
4
  type="2d"
5
5
  canvas-id="{{ canvasId }}"
6
6
  disable-scroll="true"
7
- style="width: {{ radius * 2 }}px; height: {{ radius * 2 }}px;"
7
+ style="width: {{ radius * 2 }}px; height: {{ canvasHeight }}px;"
8
8
  />
9
- <view class="lamp-temp-circle-picker-canvasPowerOffMask" style="position: absolute; top: 0; left: 0; width: {{ radius * 2 }}px; height: {{ radius * 2 }}px;" ty:if="{{ maskVisible }}" />
9
+ <view class="lamp-temp-circle-picker-canvasPowerOffMask" style="position: absolute; top: 0; left: 0; width: {{ radius * 2 }}px; height: {{ canvasHeight }}px;" ty:if="{{ maskVisible }}" />
10
10
  <canvas
11
11
  class="lamp-temp-circle-picker-canvasThumbWrapper"
12
12
  type="2d"
13
13
  canvas-id="{{ canvasId }}_thumb"
14
14
  disable-scroll="true"
15
- style="position: absolute; top: 0; left: 0; width: {{ radius * 2 }}px; height: {{ radius * 2 }}px;"
15
+ style="position: absolute; top: 0; left: 0; width: {{ radius * 2 }}px; height: {{ canvasHeight }}px;"
16
16
  />
17
17
  </view>
package/lib/index.js CHANGED
@@ -5,6 +5,8 @@ import { View, Text } from '@ray-js/components';
5
5
  import clsx from 'clsx';
6
6
  import Strings from './i18n';
7
7
  import AnnulusPickerColor from './component';
8
+ import { useStdPx2Adapt } from './hooks';
9
+ import { getArcTopPadding } from './utils';
8
10
  import './index.less';
9
11
  const LampCirclePicker = props => {
10
12
  const {
@@ -38,6 +40,10 @@ const LampCirclePicker = props => {
38
40
  const [innerCircleColor, setInnerCircleColor] = useState('');
39
41
  const innerImgRadius = innerRingRadius * 4 * 0.8;
40
42
  const _value = value !== null && value !== void 0 ? value : temperature;
43
+ const adaptedRadius = useStdPx2Adapt(radius);
44
+ const adaptedInnerRingRadius = useStdPx2Adapt(innerRingRadius);
45
+ const adaptedTouchCircleLineWidth = useStdPx2Adapt(touchCircleLineWidth);
46
+ const topPadding = useMemo(() => getArcTopPadding(adaptedRadius, adaptedInnerRingRadius, adaptedTouchCircleLineWidth), [adaptedRadius, adaptedInnerRingRadius, adaptedTouchCircleLineWidth]);
41
47
  const canvasId = useMemo(() => {
42
48
  return `canvasId_${String(+new Date()).slice(-3)}_${String(Math.random()).slice(-3)}`;
43
49
  }, []);
@@ -54,7 +60,10 @@ const LampCirclePicker = props => {
54
60
  className: clsx('lamp-temp-circle-picker-container', 'lamp-temp-circle-picker-flexCenter'),
55
61
  style: style
56
62
  }, showInnerCircle && /*#__PURE__*/React.createElement(View, {
57
- className: clsx('lamp-temp-circle-picker-innerBox', 'lamp-temp-circle-picker-flexCenter')
63
+ className: clsx('lamp-temp-circle-picker-innerBox', 'lamp-temp-circle-picker-flexCenter'),
64
+ style: {
65
+ transform: `translateY(${topPadding / 2}px)`
66
+ }
58
67
  }, /*#__PURE__*/React.createElement(View, {
59
68
  className: "lamp-temp-circle-picker-ringIcon",
60
69
  style: _objectSpread({
package/lib/index.less CHANGED
@@ -13,7 +13,6 @@
13
13
 
14
14
  .lamp-temp-circle-picker-textBox {
15
15
  flex-direction: column;
16
- position: relative;
17
16
  z-index: 100;
18
17
 
19
18
  .lamp-temp-circle-picker-title {
@@ -9,4 +9,8 @@ export declare const getSystemCacheInfo: () => {
9
9
  windowWidth: number;
10
10
  windowHeight: number;
11
11
  };
12
+ /**
13
+ * @brief Compute top padding so thumb shadow is not clipped at 270°
14
+ */
15
+ export declare function getArcTopPadding(radius: number, innerRingRadius: number, touchCircleLineWidth?: number): number;
12
16
  export { rgbToHsl, rgb2hsv, hsv2rgb };
@@ -48,4 +48,12 @@ export const getSystemCacheInfo = () => {
48
48
  }
49
49
  return __systemCacheInfo;
50
50
  };
51
+
52
+ /**
53
+ * @brief Compute top padding so thumb shadow is not clipped at 270°
54
+ */
55
+ export function getArcTopPadding(radius, innerRingRadius) {
56
+ let touchCircleLineWidth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
57
+ return Math.ceil(4 + (innerRingRadius + (radius - innerRingRadius) / 2) + (radius - innerRingRadius - 4) / 2 + (touchCircleLineWidth || 24) / 2 + 4 - radius);
58
+ }
51
59
  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.15-beta.1",
3
+ "version": "1.0.16-beta.1",
4
4
  "description": "照明缺角色环",
5
5
  "main": "lib/index",
6
6
  "files": [