Window.postMessage({触发:“ startCounting“}”,“*”);不触发

问题描述 投票:0回答:1
它不起作用,而不是动画计数的两个数字,只有一个数字闪烁而没有结束。 console窗口上的costmessage({触发:“ startCounting”},“*”); 产生相同的不必要效果

我尝试操纵动画,简化各种动作都产生了相同的结果 代码段

console.log("Version 1.77 - Explicit Viewport Trigger Integration"); class RolodexCounterElement extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); } // Specify the observed attributes static get observedAttributes() { return ["start-value", "end-value", "duration", "font-size", "font-family", "font-weight", "color"]; } // Handle attribute changes attributeChangedCallback(name, oldValue, newValue) { console.log(`Attribute changed: ${name} from ${oldValue} to ${newValue}`); if (oldValue !== newValue) { this.updateComponent(); // Re-render component with new attributes } } connectedCallback() { console.log("Rolodex Counter connected to DOM"); // Initial render this.updateComponent(); // Elements const numbersContainer = this.shadowRoot.querySelector(".frm-elmnt-numbers"); // Intersection Observer for viewport trigger const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { console.log("Element entered viewport: triggering animation"); numbersContainer.classList.add("animation"); } else { numbersContainer.classList.remove("animation"); } }); }); // Start observing the custom element observer.observe(this); // Debugging trigger for manual testing window.addEventListener("message", (event) => { if (event.data.trigger === "startCounting") { console.log("Manual trigger received"); numbersContainer.classList.add("animation"); } }); } updateComponent() { const startValue = parseInt(this.getAttribute("start-value")) || 0; const endValue = parseInt(this.getAttribute("end-value")) || 99; const duration = parseInt(this.getAttribute("duration")) || 4000; const fontSize = this.getAttribute("font-size") || "7.5rem"; const fontFamily = this.getAttribute("font-family") || "'Graphik', sans-serif"; const fontWeight = this.getAttribute("font-weight") || "300"; const color = this.getAttribute("color") || "#2e2e38"; console.log("Attributes:", { startValue, endValue, duration, fontSize, fontFamily, fontWeight, color }); // Template const template = ` <div class="frm-elmnt-counter"> <div class="frm-elmnt-numbers-wrapper"> <div class="frm-elmnt-numbers"></div> </div> <div class="frm-elmnt-percent">%</div> </div> <style> :host { display: flex; justify-content: center; align-items: center; width: auto; max-width: 100%; height: auto; max-height: 100%; background: transparent; overflow: hidden; box-sizing: border-box; } .frm-elmnt-counter { display: flex; align-items: baseline; font-size: ${fontSize}; font-weight: ${fontWeight}; font-family: ${fontFamily}; color: ${color}; line-height: 1; overflow: hidden; } .frm-elmnt-numbers-wrapper { height: ${fontSize}; overflow: hidden; position: relative; } .frm-elmnt-numbers { display: flex; flex-direction: column; transform: translateY(0); will-change: transform; } .frm-elmnt-numbers.animation { animation: frm-elmnt-roll-animation ${duration}ms ease-out forwards; } .frm-elmnt-percent { margin-left: 0.1em; font-weight: ${fontWeight}; display: inline-block; line-height: 1; position: relative; color: ${color}; font-size: ${fontSize}; font-family: ${fontFamily}; margin-left: 0.05em; /* Adjust negative margin */ padding-left: 0.05em; letter-spacing: -0.005em; } @keyframes frm-elmnt-roll-animation { 0% { transform: translateY(0); } 85% { transform: translateY(var(--final-position)); } 90% { transform: translateY(var(--overshoot-position)); } 95% { transform: translateY(var(--final-position)); } 100% { transform: translateY(var(--final-position)); } } </style> `; this.shadowRoot.innerHTML = template; // Elements const numbersContainer = this.shadowRoot.querySelector(".frm-elmnt-numbers"); const percentElement = this.shadowRoot.querySelector(".frm-elmnt-percent"); // Generate Numbers const steps = endValue - startValue + 1; const numbers = Array.from({ length: steps }, (_, i) => startValue + i); numbersContainer.innerHTML = numbers.map((num) => `<span>${num}</span>`).join(""); console.log("Generated numbers:", numbers); // Calculate Positions const rootFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize); const lineHeight = parseFloat(getComputedStyle(numbersContainer).fontSize); const remConversion = lineHeight / rootFontSize; const finalPosition = `-${(steps - 1) * remConversion}rem`; const overshootPosition = `-${(steps - 1) * remConversion + 0.3}rem`; numbersContainer.style.setProperty("--final-position", finalPosition); numbersContainer.style.setProperty("--overshoot-position", overshootPosition); // Align Percent Sign const enforceAlignment = () => { const numbersHeight = numbersContainer.offsetHeight; const percentHeight = percentElement.offsetHeight; const topAdjustment = Math.min((numbersHeight - percentHeight) / 2, 0); percentElement.style.top = `${topAdjustment}px`; }; enforceAlignment(); window.addEventListener("resize", enforceAlignment); } } customElements.define("rolodex-counter-element", RolodexCounterElement);

我看了您的代码,并设法实现了您想要的行为。

I对默认值进行了略微更改,并使用了单击事件来触发动画而不是消息...
javascript animation post message
1个回答
0
投票

console.log("Version 1.77 - Explicit Viewport Trigger Integration"); class RolodexCounterElement extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); } // Specify the observed attributes static get observedAttributes() { return ["start-value", "end-value", "duration", "font-size", "font-family", "font-weight", "color"]; } // Handle attribute changes attributeChangedCallback(name, oldValue, newValue) { console.log(`Attribute changed: ${name} from ${oldValue} to ${newValue}`); if (oldValue !== newValue) { this.updateComponent(); // Re-render component with new attributes } } connectedCallback() { console.log("Rolodex Counter connected to DOM"); // Initial render this.updateComponent(); // Elements const numbersContainer = this.shadowRoot.querySelector(".frm-elmnt-numbers"); // Intersection Observer for viewport trigger const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { console.log("Element entered viewport: triggering animation"); numbersContainer.classList.add("animation"); } else { numbersContainer.classList.remove("animation"); } }); }); // Start observing the custom element observer.observe(this); // Debugging trigger for manual testing window.addEventListener("message", (event) => { if (event.data.trigger === "startCounting") { console.log("Manual trigger received"); numbersContainer.classList.add("animation"); } }); } updateComponent() { const startValue = parseInt(this.getAttribute("start-value")) || 0; const endValue = parseInt(this.getAttribute("end-value")) || 0; // Changed from 99 to 0 const duration = parseInt(this.getAttribute("duration")) || 4000; const fontSize = this.getAttribute("font-size") || "7.5rem"; const fontFamily = this.getAttribute("font-family") || "'Graphik', sans-serif"; const fontWeight = this.getAttribute("font-weight") || "300"; const color = this.getAttribute("color") || "#2e2e38"; console.log("Attributes:", { startValue, endValue, duration, fontSize, fontFamily, fontWeight, color }); // Template const template = ` <div class="frm-elmnt-counter"> <div class="frm-elmnt-numbers-wrapper"> <div class="frm-elmnt-numbers"></div> </div> <div class="frm-elmnt-percent">%</div> </div> <style> :host { display: flex; justify-content: center; align-items: center; width: auto; max-width: 100%; height: auto; max-height: 100%; background: transparent; overflow: hidden; box-sizing: border-box; } .frm-elmnt-counter { display: flex; align-items: baseline; font-size: ${fontSize}; font-weight: ${fontWeight}; font-family: ${fontFamily}; color: ${color}; line-height: 1; overflow: hidden; } .frm-elmnt-numbers-wrapper { height: ${fontSize}; overflow: hidden; position: relative; } .frm-elmnt-numbers { display: flex; flex-direction: column; transform: translateY(0); will-change: transform; } .frm-elmnt-numbers.animation { animation: frm-elmnt-roll-animation ${duration}ms ease-out forwards; } .frm-elmnt-percent { margin-left: 0.1em; font-weight: ${fontWeight}; display: inline-block; line-height: 1; position: relative; color: ${color}; font-size: ${fontSize}; font-family: ${fontFamily}; margin-left: 0.05em; /* Adjust negative margin */ padding-left: 0.05em; letter-spacing: -0.005em; } @keyframes frm-elmnt-roll-animation { 0% { transform: translateY(0); } 85% { transform: translateY(var(--final-position)); } 90% { transform: translateY(var(--overshoot-position)); } 95% { transform: translateY(var(--final-position)); } 100% { transform: translateY(var(--final-position)); } } </style> `; this.shadowRoot.innerHTML = template; // Elements const numbersContainer = this.shadowRoot.querySelector(".frm-elmnt-numbers"); const percentElement = this.shadowRoot.querySelector(".frm-elmnt-percent"); // Generate Numbers const steps = endValue - startValue + 1; const numbers = Array.from({ length: steps }, (_, i) => startValue + i); numbersContainer.innerHTML = numbers.map((num) => `<span>${num}</span>`).join(""); console.log("Generated numbers:", numbers); // Calculate Positions const rootFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize); const lineHeight = parseFloat(getComputedStyle(numbersContainer).fontSize); const remConversion = lineHeight / rootFontSize; const finalPosition = `-${(steps - 1) * remConversion}rem`; const overshootPosition = `-${(steps - 1) * remConversion + 0.3}rem`; numbersContainer.style.setProperty("--final-position", finalPosition); numbersContainer.style.setProperty("--overshoot-position", overshootPosition); // Align Percent Sign const enforceAlignment = () => { const numbersHeight = numbersContainer.offsetHeight; const percentHeight = percentElement.offsetHeight; const topAdjustment = Math.min((numbersHeight - percentHeight) / 2, 0); percentElement.style.top = `${topAdjustment}px`; }; enforceAlignment(); window.addEventListener("resize", enforceAlignment); } } // Added this event listener that can be attached to 'message' or anything else. actionButton.addEventListener ( // Triggering the stuff on click. 'click', clickEvent => (rolodexCounter.setAttribute('end-value', 100), rolodexCounter.connectedCallback()) ); customElements.define("rolodex-counter-element", RolodexCounterElement);

<rolodex-counter-element id="rolodexCounter" start-value="0" end-value="0"></rolodex-counter-element> <button id="actionButton">Trigger 100%</button>

即使动画仍未完成,您实际上可以多次触发动画。
您只需要更改为“消息”事件侦听器,根据事件数据更改元素属性,然后像上面的示例一样触发动画。
	
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.