新的問題,來看誰更善解人意

一些和AI相关的讨论
回复
头像
ejsoon
圈圈精英
圈圈精英
帖子: 3569
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 149 次
被圈友点赞: 164 次
联系:

新的問題,來看誰更善解人意

帖子 ejsoon »

做一個html+css+js:

一,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/
弈趣極光:享受思維樂趣
头像
ejsoon
圈圈精英
圈圈精英
帖子: 3569
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 149 次
被圈友点赞: 164 次
联系:

Re: 新的問題,來看誰更善解人意

帖子 ejsoon »

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 访客