新的問題,來看誰更善解人意
新的問題,來看誰更善解人意
一,div.ejtileanimatemain中包含了.ejtileAnimateButtons和.ejtileAnimateControl,還有.ejtileAnimateResult。
二,ejtileAnimateButtons中包含button#startAnimate,button#addAnimateTransform,button#addAnimate。起初除了button#startAnimate之外,其它都不顯示。
三,當點擊button#startAnimate,js將把svg#etmain的clone去除.etwait,把.etdrop的transform設置為translate(240,240) scale(1,1),之後顯示至ejtileAnimateResult,button#startAnimate的inner也從start變成end。其它元素也將顯示。
四,當點擊button#addAnimateTransform時:
1.js將拿到use.tilemoving。如果沒有,則無效;如果有,則取其href,transform。
2.js將在ejtileAnimateControl中增加一個div.animatePanel,內含h4{animateTransform},button{add value},label{values}>input[type=input],label{dur}>input[type=input],label{begin}>input[type=input]。
3.增加一個<animateTransform animateType=translate>到ejtileAnimateResult對應的use-href中。animateTransform的id是ani_index,index指從0開始遞增的整數。values是當前use.tilemoving的Transform-translate。
4.同時增加一個<animateTransform animateType=scale>到ejtileAnimateResult對應的use-href中。id是ani_index,index比前一個大1。values是當前use.tilemoving的Transform-scale。additive=sum。
5.同時增加的兩個animateTransform用同一個animatePanel控制。如果是首個animatePanel,則兩個animateTransform的begin是0,如果不是首個animatePanel,則begin為前一個ani_index.end。
6.<animateTransform/>的模板為:<animateTransform id="ani_2" attributeName="transform" attributeType="XML" type="translate" values="0,-120;-60,60" dur="2s" fill="freeze" begin="ani_1.end"/>
7.當點擊button{add value},對應的兩個animateTransform的values就增加一個值,該值從當前的use.tilemoving上獲取。dur加1s。
8.animatePanel中的input手動更改時,ejtileAnimateResult也將實時顯示。
五,當點擊button#addAnimate時:
1.js將拿到use.tilemoving。如果沒有,則無效;如果有,則取其href,transform。
2.js將在ejtileAnimateControl中增加一個div.animatePanel2,內含h4{animate},select#animateAttribute,label{values}>input[type=input],label{dur}>input[type=input],label{begin}>input[type=input]。select#animateAttribute的option包括opacity,fill,stroke,stroke-width,也可以手動填寫。
3.增加一個<animate>到ejtileAnimateResult對應的use-href中。animate的id是ani_index,index指從0開始遞增的整數。values需手動填。begin默認值為前一個ani_index.end。
4.<animate/>的模板為:<animate id="ani_2" attributeName="opacity" values="0;1" dur="1s" fill="freeze" begin="ani_1.end"/>
5.當animatePanel2中的input更改時,ejtileAnimateResult也將實時顯示。
五,ejtileAnimateResult含有一個實時顯示圖片結果的img,以及div.download>(a.anidownload+span.anisvgsize)。anidownload點擊則下載該svgresult,anisvgsize顯示它的size-byte。
六,當button#startAnimate-end再次點擊時,button#addAnimate的inner變回start。ejtileAnimateControl,還有ejtileAnimateResult元素清空。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
弈趣極光:享受思維樂趣
Re: 新的問題,來看誰更善解人意
gemini
代码: 全选
好的,這是一個相當複雜的 HTML、CSS 和 JavaScript 實現。我將分步驟解釋如何構建這個動畫控制介面。
**HTML (index.html):**
```html
<!DOCTYPE html>
<html>
<head>
<title>SVG Animation Control</title>
<style>
/* CSS 樣式 (見下方) */
</style>
</head>
<body>
<div class="ejtileanimatemain">
<div class="ejtileAnimateButtons">
<button id="startAnimate">Start</button>
</div>
<div class="ejtileAnimateControl"></div>
<div class="ejtileAnimateResult">
<img id="resultImg" src="" alt="Animation Result">
<div class="download">
<a class="anidownload" href="#" download="animation.svg">Download SVG</a>
<span class="anisvgsize"></span>
</div>
</div>
</div>
<svg id="etmain" width="480" height="480" style="display: none;">
<defs>
<g id="tilemoving">
<rect width="100" height="100" fill="red" />
</g>
</defs>
<use href="#tilemoving" class="etdrop" transform="translate(0,0) scale(1,1)" />
<g id="etwait">
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">請點擊Start</text>
</g>
</svg>
<script>
// JavaScript 程式碼 (見下方)
</script>
</body>
</html>
```
**CSS (style 標籤內):**
```css
.ejtileanimatemain {
display: flex;
flex-direction: column;
width: 600px;
}
.ejtileAnimateButtons {
margin-bottom: 10px;
}
.ejtileAnimateControl {
margin-bottom: 10px;
}
.animatePanel, .animatePanel2 {
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 5px;
}
.animatePanel label, .animatePanel2 label {
display: block;
margin-bottom: 5px;
}
.ejtileAnimateResult img {
max-width: 100%;
}
.ejtileAnimateResult .download {
margin-top: 10px;
}
#startAnimate, #addAnimateTransform, #addAnimate {
margin-right: 5px;
}
```
**JavaScript (script 標籤內):**
```javascript
const startButton = document.getElementById('startAnimate');
const buttonsDiv = document.querySelector('.ejtileAnimateButtons');
const controlDiv = document.querySelector('.ejtileAnimateControl');
const resultDiv = document.querySelector('.ejtileAnimateResult');
const etmain = document.getElementById('etmain');
const tilemoving = document.querySelector('use.etdrop');
const resultImg = document.getElementById('resultImg');
const anidownload = document.querySelector('.anidownload');
const anisvgsize = document.querySelector('.anisvgsize');
let aniIndex = 0;
let isAnimating = false;
function updateResult() {
const svgString = new XMLSerializer().serializeToString(etmain);
const blob = new Blob([svgString], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
resultImg.src = url;
anidownload.href = url;
anisvgsize.textContent = `${blob.size} bytes`;
}
function addAnimateTransformPanel(useElement) {
const panel = document.createElement('div');
panel.classList.add('animatePanel');
panel.innerHTML = `
<h4>animateTransform</h4>
<button class="addValue">Add Value</button>
<label>Values: <input type="text" class="values" value="${useElement.getAttribute('transform').match(/translate\((.*?)\)/)[1]};${useElement.getAttribute('transform').match(/scale\((.*?)\)/)[1]}" /></label>
<label>Dur: <input type="text" class="dur" value="1s" /></label>
<label>Begin: <input type="text" class="begin" value="${aniIndex === 0 ? '0' : `ani_${aniIndex - 2}.end`}" /></label>
`;
controlDiv.appendChild(panel);
const translateAni = document.createElementNS('http://www.w3.org/2000/svg', 'animateTransform');
translateAni.setAttribute('id', `ani_${aniIndex}`);
translateAni.setAttribute('attributeName', 'transform');
translateAni.setAttribute('attributeType', 'XML');
translateAni.setAttribute('type', 'translate');
translateAni.setAttribute('values', useElement.getAttribute('transform').match(/translate\((.*?)\)/)[1]);
translateAni.setAttribute('dur', '1s');
translateAni.setAttribute('fill', 'freeze');
translateAni.setAttribute('begin', aniIndex === 0 ? '0' : `ani_${aniIndex - 2}.end`);
useElement.appendChild(translateAni);
aniIndex++;
const scaleAni = document.createElementNS('http://www.w3.org/2000/svg', 'animateTransform');
scaleAni.setAttribute('id', `ani_${aniIndex}`);
scaleAni.setAttribute('attributeName', 'transform');
scaleAni.setAttribute('attributeType', 'XML');
scaleAni.setAttribute('type', 'scale');
scaleAni.setAttribute('values', useElement.getAttribute('transform').match(/scale\((.*?)\)/)[1]);
scaleAni.setAttribute('dur', '1s');
scaleAni.setAttribute('fill', 'freeze');
scaleAni.setAttribute('begin', aniIndex === 0 ? '0' : `ani_${aniIndex - 2}.end`);
scaleAni.setAttribute('additive', 'sum');
useElement.appendChild(scaleAni);
aniIndex++;
const addValueButton = panel.querySelector('.addValue');
const valuesInput = panel.querySelector('.values');
const durInput = panel.querySelector('.dur');
const beginInput = panel.querySelector('.begin');
addValueButton.addEventListener('click', () => {
valuesInput.value += `;${useElement.getAttribute('transform').match(/translate\((.*?)\)/)[1]};${useElement.getAttribute('transform').match(/scale\((.*?)\)/)[1]}`;
durInput.value = `${parseFloat(durInput.value) + 1}s`;
translateAni.setAttribute('values', valuesInput.value.split(';').filter((_, i) => i % 2 === 0).join(';'));
scaleAni.setAttribute('values', valuesInput.value.split(';').filter((_, i) => i % 2 !== 0).join(';'));
translateAni.setAttribute('dur', durInput.value);
scaleAni.setAttribute('dur', durInput.value);
updateResult();
});
valuesInput.addEventListener('input', () => {
translateAni.setAttribute('values', valuesInput.value.split(';').filter((_, i) => i % 2 === 0).join(';'));
scaleAni.setAttribute('values', valuesInput.value.split(';').filter((_, i) => i % 2 !== 0).join(';'));
updateResult();
});
durInput.addEventListener('input', () => {
translateAni.setAttribute('dur', durInput.value);
scaleAni.setAttribute('dur', durInput.value);
updateResult();
});
beginInput.addEventListener('input', () => {
translateAni.setAttribute('begin', beginInput.value);
scaleAni.setAttribute('begin', beginInput.value);
updateResult();
});
updateResult();
}
function addAnimatePanel(useElement) {
const panel = document.createElement('div');
panel.classList.add('animatePanel2');
panel.innerHTML = `
<h4>animate</h4>
<select id="animateAttribute">
<option value="opacity">opacity</option>
<option value="fill">fill</option>
<option value="stroke">stroke</option>
<option value="stroke-width">stroke-width</option>
</select>
<label>Values: <input type="text" class="values" value="0;1" /></label>
<label>Dur: <input type="text" class="dur" value="1s" /></label>
<label>Begin: <input type="text" class="begin" value="${aniIndex === 0 ? '0' : `ani_${aniIndex - 1}.end`}" /></label>
`;
controlDiv.appendChild(panel);
const animateElement = document.createElementNS('http://www.w3.org/2000/svg', 'animate');
animateElement.setAttribute('id', `ani_${aniIndex}`);
animateElement.setAttribute('attributeName', 'opacity');
animateElement.setAttribute('values', '0;1');
animateElement.setAttribute('dur', '1s');
animateElement.setAttribute('fill', 'freeze');
animateElement.setAttribute('begin', aniIndex === 0 ? '0' : `ani_${aniIndex - 1}.end`);
useElement.appendChild(animateElement);
aniIndex++;
const attributeSelect = panel.querySelector('#animateAttribute');
const valuesInput = panel.querySelector('.values');
const durInput = panel.querySelector('.dur');
const beginInput = panel.querySelector('.begin');
attributeSelect.addEventListener('change', () => {
animateElement.setAttribute('attributeName', attributeSelect.value);
updateResult();
});
valuesInput.addEventListener('input', () => {
animateElement.setAttribute('values', valuesInput.value);
updateResult();
});
durInput.addEventListener('input', () => {
animateElement.setAttribute('dur', durInput.value);
updateResult();
});
beginInput.addEventListener('input', () => {
animateElement.setAttribute('begin', beginInput.value);
updateResult();
});
updateResult();
}
startButton.addEventListener('click', () => {
if (!isAnimating) {
etmain.removeChild(document.getElementById('etwait'));
tilemoving.setAttribute('transform', 'translate(240,240) scale(1,1)');
resultDiv.style.display = 'block';
startButton.textContent = 'End';
buttonsDiv.appendChild(document.createElement('button')).id='addAnimateTransform';
buttonsDiv.appendChild(document.createElement('button')).id='addAnimate';
document.getElementById('addAnimateTransform').innerHTML = 'Add Transform';
document.getElementById('addAnimate').innerHTML = 'Add Animate';
document.getElementById('addAnimateTransform').addEventListener('click', () => {
if (tilemoving) {
addAnimateTransformPanel(tilemoving);
}
});
document.getElementById('addAnimate').addEventListener('click', () => {
if (tilemoving) {
addAnimatePanel(tilemoving);
}
});
isAnimating = true;
updateResult();
} else {
startButton.textContent = 'Start';
controlDiv.innerHTML = '';
resultDiv.style.display = 'none';
etmain.appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'g')).id = 'etwait';
document.getElementById('etwait').appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'text'));
document.getElementById('etwait').firstChild.setAttribute('x','50%');
document.getElementById('etwait').firstChild.setAttribute('y','50%');
document.getElementById('etwait').firstChild.setAttribute('dominant-baseline','middle');
document.getElementById('etwait').firstChild.setAttribute('text-anchor','middle');
document.getElementById('etwait').firstChild.innerHTML = '請點擊Start';
tilemoving.innerHTML = '';
tilemoving.setAttribute('transform', 'translate(0,0) scale(1,1)');
aniIndex = 0;
isAnimating = false;
}
});
```
**程式碼說明:**
* **`updateResult()` 函數:**
* 將 SVG 轉換為字串,然後創建 Blob 和 URL,用於顯示影像和下載。
* 更新下載連結和 SVG 大小。
* **`addAnimateTransformPanel(useElement)` 函數:**
* 創建一個 `animatePanel`,用於控制 `animateTransform`。
* 添加 `animateTransform` 元素到 `useElement`。
* 處理 "Add Value" 按鈕的點擊事件,以添加新的動畫值。
* 處理輸入欄位的更改事件,以更新動畫。
* **`addAnimatePanel(useElement)` 函數:**
* 創建一個 `animatePanel2`,用於控制 `animate`。
* 添加 `animate` 元素到 `useElement`。
* 處理選項和輸入欄位的更改事件,以更新動畫。
* **`startButton.addEventListener('click', ...)`:**
* 處理 "Start" 和 "End" 按鈕的點擊事件。
* 切換動畫狀態,顯示/隱藏控制面板和結果。
* 在Start狀態下,刪除等待文字,增加控制按鈕,並添加監聽器。
* 在End狀態下,清空所有動畫,重置svg。
* **初始狀態:**
* 隱藏控制面板和結果。
* SVG 包含一個預設的 `use` 元素。
**如何使用:**
1. 將 HTML、CSS 和 JavaScript 程式碼保存到一個 `.html` 檔案中。
2. 在瀏覽器中打開該檔案。
3. 點擊 "Start" 按鈕開始動畫控制。
4. 使用 "Add Transform" 和 "Add Animate" 按鈕添加動畫。
5. 使用控制面板調整動畫參數。
6. 點擊 "End" 按鈕停止動畫並重置。
7. 點擊 "Download SVG" 下載產生的 SVG 影像。
這個實現提供了一個基本的動畫控制介面。你可以根據需要擴展和修改它。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
弈趣極光:享受思維樂趣
在线用户
正浏览此版面之用户: Ahrefs [Bot] 和 0 访客