Skip to content

Commit 57c5e6f

Browse files
committed
Refactor PolinePicker to optimize ring rendering and hover effects
- Removed individual hover classes for ring ticks and backgrounds, consolidating hover styles into group classes. - Updated the rendering logic to use a single group element for each anchor, containing the background ring, saturation arc, and tick. - Enhanced performance by reducing the number of DOM manipulations when updating saturation rings. - Added media query handling to hide ring groups on touch devices, preventing unnecessary interactions. - Adjusted pointer event handling to skip ring detection on touch devices, improving usability.
1 parent 0806a4d commit 57c5e6f

File tree

7 files changed

+237
-245
lines changed

7 files changed

+237
-245
lines changed

dist/picker.cjs

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -746,9 +746,6 @@ var PolinePicker = class extends HTMLElement {
746746
pointer-events: none;
747747
opacity: 0;
748748
}
749-
.wheel__ring-tick--hover {
750-
opacity: 1;
751-
}
752749
.wheel__ring-bg {
753750
fill: none;
754751
stroke: var(--poline-picker-bg-color, #fff);
@@ -757,8 +754,16 @@ var PolinePicker = class extends HTMLElement {
757754
vector-effect: non-scaling-stroke;
758755
opacity: 0;
759756
}
760-
.wheel__ring-bg--hover {
761-
opacity: 0.3;
757+
.wheel__ring-group--hover .wheel__ring-tick {
758+
opacity: 1;
759+
}
760+
.wheel__ring-group--hover .wheel__ring-bg {
761+
opacity: 1;
762+
}
763+
@media (pointer: coarse) {
764+
.wheel__ring-group {
765+
display: none;
766+
}
762767
}
763768
:host(.ring-hover) svg {
764769
cursor: ew-resize;
@@ -855,12 +860,13 @@ var PolinePicker = class extends HTMLElement {
855860
if (!this.poline || !this.saturationRings)
856861
return;
857862
const anchors = this.poline.anchorPoints;
858-
const existing = this.saturationRings.children;
859-
const elementsPerAnchor = 3;
860-
while (existing.length > anchors.length * elementsPerAnchor) {
861-
const last = existing[existing.length - 1];
863+
const ringGroups = Array.from(
864+
this.saturationRings.querySelectorAll(".wheel__ring-group")
865+
);
866+
while (ringGroups.length > anchors.length) {
867+
const last = ringGroups.pop();
862868
if (last)
863-
this.saturationRings.removeChild(last);
869+
last.remove();
864870
}
865871
anchors.forEach((anchor, i) => {
866872
const cartesian = this.pointToCartesian(anchor);
@@ -870,26 +876,30 @@ var PolinePicker = class extends HTMLElement {
870876
const saturation = anchor.z;
871877
const ringRadius = UI_METRICS.anchorRadius + UI_METRICS.ringGap + 1;
872878
const isHovered = this.ringHoverIndex === i || this.ringAdjust && this.ringAdjust.anchorIndex === i;
873-
let bgRing = existing[i * elementsPerAnchor];
874-
if (!bgRing) {
875-
bgRing = document.createElementNS(namespaceURI, "circle");
876-
bgRing.setAttribute("class", "wheel__ring-bg");
877-
this.saturationRings.appendChild(bgRing);
879+
let group = ringGroups[i];
880+
if (!group) {
881+
group = document.createElementNS(namespaceURI, "g");
882+
group.setAttribute("class", "wheel__ring-group");
883+
const bgRing2 = document.createElementNS(namespaceURI, "circle");
884+
bgRing2.setAttribute("class", "wheel__ring-bg");
885+
group.appendChild(bgRing2);
886+
const satArc2 = document.createElementNS(namespaceURI, "path");
887+
satArc2.setAttribute("class", "wheel__saturation-ring");
888+
group.appendChild(satArc2);
889+
const tick2 = document.createElementNS(namespaceURI, "line");
890+
tick2.setAttribute("class", "wheel__ring-tick");
891+
group.appendChild(tick2);
892+
this.saturationRings.appendChild(group);
893+
ringGroups.push(group);
878894
}
895+
group.classList.toggle("wheel__ring-group--hover", !!isHovered);
896+
const bgRing = group.querySelector(".wheel__ring-bg");
879897
bgRing.setAttribute("cx", cx.toString());
880898
bgRing.setAttribute("cy", cy.toString());
881899
bgRing.setAttribute("r", ringRadius.toString());
882-
bgRing.setAttribute(
883-
"stroke-width",
884-
(isHovered ? UI_METRICS.ringThicknessHover : UI_METRICS.ringThickness).toString()
900+
const satArc = group.querySelector(
901+
".wheel__saturation-ring"
885902
);
886-
bgRing.classList.toggle("wheel__ring-bg--hover", !!isHovered);
887-
let satArc = existing[i * elementsPerAnchor + 1];
888-
if (!satArc) {
889-
satArc = document.createElementNS(namespaceURI, "path");
890-
satArc.setAttribute("class", "wheel__saturation-ring");
891-
this.saturationRings.appendChild(satArc);
892-
}
893903
const startAngle = -Math.PI / 2;
894904
const endAngle = startAngle + saturation * Math.PI * 2;
895905
const arcPath = this.describeArc(
@@ -900,32 +910,15 @@ var PolinePicker = class extends HTMLElement {
900910
endAngle
901911
);
902912
satArc.setAttribute("d", arcPath);
903-
satArc.setAttribute(
904-
"stroke-width",
905-
(isHovered ? UI_METRICS.ringThicknessHover : UI_METRICS.ringThickness).toString()
906-
);
907-
satArc.classList.toggle("wheel__saturation-ring--hover", !!isHovered);
908-
let tick = existing[i * elementsPerAnchor + 2];
909-
if (!tick) {
910-
tick = document.createElementNS(namespaceURI, "line");
911-
tick.setAttribute("class", "wheel__ring-tick");
912-
this.saturationRings.appendChild(tick);
913-
}
914-
const dirX = Math.cos(endAngle);
915-
const dirY = Math.sin(endAngle);
913+
const tick = group.querySelector(".wheel__ring-tick");
916914
const tickStartX = cx + (ringRadius + UI_METRICS.tickGap) * Math.cos(endAngle);
917915
const tickStartY = cy + (ringRadius + UI_METRICS.tickGap) * Math.sin(endAngle);
918-
const tickEndX = tickStartX + dirX * UI_METRICS.tickLength;
919-
const tickEndY = tickStartY + dirY * UI_METRICS.tickLength;
916+
const tickEndX = tickStartX + Math.cos(endAngle) * UI_METRICS.tickLength;
917+
const tickEndY = tickStartY + Math.sin(endAngle) * UI_METRICS.tickLength;
920918
tick.setAttribute("x1", tickStartX.toString());
921919
tick.setAttribute("y1", tickStartY.toString());
922920
tick.setAttribute("x2", tickEndX.toString());
923921
tick.setAttribute("y2", tickEndY.toString());
924-
tick.setAttribute(
925-
"stroke-width",
926-
(isHovered ? UI_METRICS.ringThicknessHover : UI_METRICS.ringThickness).toString()
927-
);
928-
tick.classList.toggle("wheel__ring-tick--hover", !!isHovered);
929922
});
930923
}
931924
describeArc(cx, cy, r, startAngle, endAngle) {
@@ -972,7 +965,8 @@ var PolinePicker = class extends HTMLElement {
972965
handlePointerDown(e) {
973966
e.stopPropagation();
974967
const { normalizedX, normalizedY } = this.pointerToNormalizedCoordinates(e);
975-
const ringHit = this.pickRing(normalizedX, normalizedY);
968+
const isTouch = window.matchMedia("(pointer: coarse)").matches;
969+
const ringHit = isTouch ? null : this.pickRing(normalizedX, normalizedY);
976970
if (ringHit !== null) {
977971
const anchor = this.poline.anchorPoints[ringHit];
978972
if (!anchor)
@@ -1069,11 +1063,13 @@ var PolinePicker = class extends HTMLElement {
10691063
this.dispatchPolineChange();
10701064
return;
10711065
}
1072-
const ringHover = this.pickRing(normalizedX, normalizedY);
1073-
if (ringHover !== this.ringHoverIndex) {
1074-
this.ringHoverIndex = ringHover;
1075-
this.classList.toggle("ring-hover", ringHover !== null);
1076-
this.updateSaturationRings();
1066+
if (!window.matchMedia("(pointer: coarse)").matches) {
1067+
const ringHover = this.pickRing(normalizedX, normalizedY);
1068+
if (ringHover !== this.ringHoverIndex) {
1069+
this.ringHoverIndex = ringHover;
1070+
this.classList.toggle("ring-hover", ringHover !== null);
1071+
this.updateSaturationRings();
1072+
}
10771073
}
10781074
}
10791075
handlePointerUp(e) {

dist/picker.js

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -746,9 +746,6 @@ var polinePicker = (() => {
746746
pointer-events: none;
747747
opacity: 0;
748748
}
749-
.wheel__ring-tick--hover {
750-
opacity: 1;
751-
}
752749
.wheel__ring-bg {
753750
fill: none;
754751
stroke: var(--poline-picker-bg-color, #fff);
@@ -757,8 +754,16 @@ var polinePicker = (() => {
757754
vector-effect: non-scaling-stroke;
758755
opacity: 0;
759756
}
760-
.wheel__ring-bg--hover {
761-
opacity: 0.3;
757+
.wheel__ring-group--hover .wheel__ring-tick {
758+
opacity: 1;
759+
}
760+
.wheel__ring-group--hover .wheel__ring-bg {
761+
opacity: 1;
762+
}
763+
@media (pointer: coarse) {
764+
.wheel__ring-group {
765+
display: none;
766+
}
762767
}
763768
:host(.ring-hover) svg {
764769
cursor: ew-resize;
@@ -855,12 +860,13 @@ var polinePicker = (() => {
855860
if (!this.poline || !this.saturationRings)
856861
return;
857862
const anchors = this.poline.anchorPoints;
858-
const existing = this.saturationRings.children;
859-
const elementsPerAnchor = 3;
860-
while (existing.length > anchors.length * elementsPerAnchor) {
861-
const last = existing[existing.length - 1];
863+
const ringGroups = Array.from(
864+
this.saturationRings.querySelectorAll(".wheel__ring-group")
865+
);
866+
while (ringGroups.length > anchors.length) {
867+
const last = ringGroups.pop();
862868
if (last)
863-
this.saturationRings.removeChild(last);
869+
last.remove();
864870
}
865871
anchors.forEach((anchor, i) => {
866872
const cartesian = this.pointToCartesian(anchor);
@@ -870,26 +876,30 @@ var polinePicker = (() => {
870876
const saturation = anchor.z;
871877
const ringRadius = UI_METRICS.anchorRadius + UI_METRICS.ringGap + 1;
872878
const isHovered = this.ringHoverIndex === i || this.ringAdjust && this.ringAdjust.anchorIndex === i;
873-
let bgRing = existing[i * elementsPerAnchor];
874-
if (!bgRing) {
875-
bgRing = document.createElementNS(namespaceURI, "circle");
876-
bgRing.setAttribute("class", "wheel__ring-bg");
877-
this.saturationRings.appendChild(bgRing);
879+
let group = ringGroups[i];
880+
if (!group) {
881+
group = document.createElementNS(namespaceURI, "g");
882+
group.setAttribute("class", "wheel__ring-group");
883+
const bgRing2 = document.createElementNS(namespaceURI, "circle");
884+
bgRing2.setAttribute("class", "wheel__ring-bg");
885+
group.appendChild(bgRing2);
886+
const satArc2 = document.createElementNS(namespaceURI, "path");
887+
satArc2.setAttribute("class", "wheel__saturation-ring");
888+
group.appendChild(satArc2);
889+
const tick2 = document.createElementNS(namespaceURI, "line");
890+
tick2.setAttribute("class", "wheel__ring-tick");
891+
group.appendChild(tick2);
892+
this.saturationRings.appendChild(group);
893+
ringGroups.push(group);
878894
}
895+
group.classList.toggle("wheel__ring-group--hover", !!isHovered);
896+
const bgRing = group.querySelector(".wheel__ring-bg");
879897
bgRing.setAttribute("cx", cx.toString());
880898
bgRing.setAttribute("cy", cy.toString());
881899
bgRing.setAttribute("r", ringRadius.toString());
882-
bgRing.setAttribute(
883-
"stroke-width",
884-
(isHovered ? UI_METRICS.ringThicknessHover : UI_METRICS.ringThickness).toString()
900+
const satArc = group.querySelector(
901+
".wheel__saturation-ring"
885902
);
886-
bgRing.classList.toggle("wheel__ring-bg--hover", !!isHovered);
887-
let satArc = existing[i * elementsPerAnchor + 1];
888-
if (!satArc) {
889-
satArc = document.createElementNS(namespaceURI, "path");
890-
satArc.setAttribute("class", "wheel__saturation-ring");
891-
this.saturationRings.appendChild(satArc);
892-
}
893903
const startAngle = -Math.PI / 2;
894904
const endAngle = startAngle + saturation * Math.PI * 2;
895905
const arcPath = this.describeArc(
@@ -900,32 +910,15 @@ var polinePicker = (() => {
900910
endAngle
901911
);
902912
satArc.setAttribute("d", arcPath);
903-
satArc.setAttribute(
904-
"stroke-width",
905-
(isHovered ? UI_METRICS.ringThicknessHover : UI_METRICS.ringThickness).toString()
906-
);
907-
satArc.classList.toggle("wheel__saturation-ring--hover", !!isHovered);
908-
let tick = existing[i * elementsPerAnchor + 2];
909-
if (!tick) {
910-
tick = document.createElementNS(namespaceURI, "line");
911-
tick.setAttribute("class", "wheel__ring-tick");
912-
this.saturationRings.appendChild(tick);
913-
}
914-
const dirX = Math.cos(endAngle);
915-
const dirY = Math.sin(endAngle);
913+
const tick = group.querySelector(".wheel__ring-tick");
916914
const tickStartX = cx + (ringRadius + UI_METRICS.tickGap) * Math.cos(endAngle);
917915
const tickStartY = cy + (ringRadius + UI_METRICS.tickGap) * Math.sin(endAngle);
918-
const tickEndX = tickStartX + dirX * UI_METRICS.tickLength;
919-
const tickEndY = tickStartY + dirY * UI_METRICS.tickLength;
916+
const tickEndX = tickStartX + Math.cos(endAngle) * UI_METRICS.tickLength;
917+
const tickEndY = tickStartY + Math.sin(endAngle) * UI_METRICS.tickLength;
920918
tick.setAttribute("x1", tickStartX.toString());
921919
tick.setAttribute("y1", tickStartY.toString());
922920
tick.setAttribute("x2", tickEndX.toString());
923921
tick.setAttribute("y2", tickEndY.toString());
924-
tick.setAttribute(
925-
"stroke-width",
926-
(isHovered ? UI_METRICS.ringThicknessHover : UI_METRICS.ringThickness).toString()
927-
);
928-
tick.classList.toggle("wheel__ring-tick--hover", !!isHovered);
929922
});
930923
}
931924
describeArc(cx, cy, r, startAngle, endAngle) {
@@ -972,7 +965,8 @@ var polinePicker = (() => {
972965
handlePointerDown(e) {
973966
e.stopPropagation();
974967
const { normalizedX, normalizedY } = this.pointerToNormalizedCoordinates(e);
975-
const ringHit = this.pickRing(normalizedX, normalizedY);
968+
const isTouch = window.matchMedia("(pointer: coarse)").matches;
969+
const ringHit = isTouch ? null : this.pickRing(normalizedX, normalizedY);
976970
if (ringHit !== null) {
977971
const anchor = this.poline.anchorPoints[ringHit];
978972
if (!anchor)
@@ -1069,11 +1063,13 @@ var polinePicker = (() => {
10691063
this.dispatchPolineChange();
10701064
return;
10711065
}
1072-
const ringHover = this.pickRing(normalizedX, normalizedY);
1073-
if (ringHover !== this.ringHoverIndex) {
1074-
this.ringHoverIndex = ringHover;
1075-
this.classList.toggle("ring-hover", ringHover !== null);
1076-
this.updateSaturationRings();
1066+
if (!window.matchMedia("(pointer: coarse)").matches) {
1067+
const ringHover = this.pickRing(normalizedX, normalizedY);
1068+
if (ringHover !== this.ringHoverIndex) {
1069+
this.ringHoverIndex = ringHover;
1070+
this.classList.toggle("ring-hover", ringHover !== null);
1071+
this.updateSaturationRings();
1072+
}
10771073
}
10781074
}
10791075
handlePointerUp(e) {

0 commit comments

Comments
 (0)