{"id":9036,"date":"2025-09-17T13:24:23","date_gmt":"2025-09-17T04:24:23","guid":{"rendered":"https:\/\/code-plus.jp\/gp\/?page_id=9036"},"modified":"2026-04-02T14:21:43","modified_gmt":"2026-04-02T05:21:43","slug":"svg2gif-converter","status":"publish","type":"page","link":"https:\/\/code-plus.jp\/gp\/tools\/svg2gif-converter\/","title":{"rendered":"svg2gif-converter"},"content":{"rendered":"<style>\r\n  * {\r\n  margin: 0;\r\n  padding: 0;\r\n  box-sizing: border-box;\r\n  }\r\n  \r\n  body {\r\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;\r\n  background: #f5f5f5;\r\n  min-height: 100vh;\r\n  padding: 20px;\r\n  }\r\n  \r\n  .container {\r\n  max-width: 1200px;\r\n  margin: 0 auto;\r\n  background: white;\r\n  border-radius: 12px;\r\n  box-shadow: 0 2px 10px rgba(0,0,0,0.1);\r\n  overflow: hidden;\r\n  }\r\n  \r\n  .header {\r\n  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\r\n  color: white;\r\n  padding: 30px;\r\n  text-align: center;\r\n  }\r\n  \r\n  .header h1 {\r\n  font-size: 2em;\r\n  margin-bottom: 10px;\r\n  }\r\n  \r\n  .header p {\r\n  opacity: 0.9;\r\n  font-size: 1.1em;\r\n  }\r\n  \r\n  .content {\r\n  display: grid;\r\n  grid-template-columns: 1fr 1fr;\r\n  gap: 30px;\r\n  padding: 40px;\r\n  }\r\n  \r\n  @media (max-width: 768px) {\r\n  .content {\r\n  grid-template-columns: 1fr;\r\n  }\r\n  }\r\n  \r\n  .column {\r\n  display: flex;\r\n  flex-direction: column;\r\n  }\r\n  \r\n  .column h3 {\r\n  color: #333;\r\n  margin-bottom: 20px;\r\n  font-size: 1.3em;\r\n  }\r\n  \r\n  .endropArea {\r\n  border: 3px dashed #ccc;\r\n  border-radius: 15px;\r\n  padding: 40px;\r\n  text-align: center;\r\n  cursor: pointer;\r\n  transition: all 0.3s;\r\n  background: #fafafa;\r\n  min-height: 350px;\r\n  display: flex;\r\n  flex-direction: column;\r\n  justify-content: center;\r\n  align-items: center;\r\n  }\r\n  \r\n  .endropArea:hover {\r\n  border-color: #667eea;\r\n  background: #f0f0ff;\r\n  }\r\n  \r\n  .endropArea.dragover {\r\n  background: #e8e8ff;\r\n  border-color: #764ba2;\r\n  }\r\n  \r\n  .endropArea.has-file {\r\n  border-color: #4CAF50;\r\n  background: #f1f8f4;\r\n  }\r\n  \r\n  .endrop-icon {\r\n  font-size: 48px;\r\n  margin-bottom: 20px;\r\n  }\r\n  \r\n  .endrop-text {\r\n  font-size: 1.2em;\r\n  color: #666;\r\n  margin-bottom: 10px;\r\n  }\r\n  \r\n  .drop-subtext {\r\n  font-size: 0.9em;\r\n  color: #999;\r\n  }\r\n  \r\n  .file-input {\r\n  display: none;\r\n  }\r\n  \r\n  .preview-area {\r\n  border: 2px solid #e0e0e0;\r\n  border-radius: 15px;\r\n  padding: 20px;\r\n  background: #fafafa;\r\n  min-height: 350px;\r\n  display: flex;\r\n  flex-direction: column;\r\n  align-items: center;\r\n  justify-content: center;\r\n  }\r\n  \r\n  .preview-area canvas {\r\n  max-width: 100%;\r\n  border-radius: 8px;\r\n  box-shadow: 0 2px 8px rgba(0,0,0,0.1);\r\n  }\r\n  \r\n  .preview-placeholder {\r\n  color: #999;\r\n  font-size: 1.1em;\r\n  text-align: center;\r\n  }\r\n  \r\n  .controls {\r\n  margin-top: 20px;\r\n  padding: 20px;\r\n  background: #f9f9f9;\r\n  border-radius: 10px;\r\n  }\r\n  \r\n  .control-group {\r\n  margin-bottom: 20px;\r\n  }\r\n  \r\n  .control-group label {\r\n  display: block;\r\n  color: #555;\r\n  margin-bottom: 8px;\r\n  font-weight: 500;\r\n  }\r\n  \r\n  .control-group input[type=\"range\"] {\r\n  width: 100%;\r\n  margin-bottom: 5px;\r\n  }\r\n  \r\n  .control-value {\r\n  color: #667eea;\r\n  font-weight: bold;\r\n  float: right;\r\n  }\r\n  \r\n  .button {\r\n  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\r\n  color: white;\r\n  border: none;\r\n  padding: 12px 30px;\r\n  border-radius: 25px;\r\n  font-size: 1.1em;\r\n  cursor: pointer;\r\n  transition: all 0.3s;\r\n  margin-top: 20px;\r\n  width: 100%;\r\n  box-shadow: 0 4px 15px 0 rgba(102, 126, 234, 0.4);\r\n  }\r\n  \r\n  .button:hover {\r\n  transform: translateY(-2px);\r\n  box-shadow: 0 6px 20px 0 rgba(102, 126, 234, 0.5);\r\n  }\r\n  \r\n  .button:disabled {\r\n  background: linear-gradient(135deg, #ccc 0%, #999 100%);\r\n  cursor: not-allowed;\r\n  box-shadow: none;\r\n  }\r\n  \r\n  .button:disabled:hover {\r\n  transform: none;\r\n  }\r\n  \r\n  .download-button {\r\n  background: linear-gradient(135deg, #56ab2f 0%, #a8e063 100%);\r\n  display: none;\r\n  box-shadow: 0 4px 15px 0 rgba(86, 171, 47, 0.4);\r\n  }\r\n  \r\n  .download-button:hover {\r\n  box-shadow: 0 6px 20px 0 rgba(86, 171, 47, 0.5);\r\n  }\r\n  \r\n  .download-button.show {\r\n  display: block;\r\n  }\r\n  \r\n  .status-message {\r\n  padding: 15px;\r\n  border-radius: 8px;\r\n  margin-top: 20px;\r\n  text-align: center;\r\n  display: none;\r\n  font-weight: 500;\r\n  }\r\n  \r\n  .status-message.success {\r\n  background: #d4edda;\r\n  color: #155724;\r\n  border: 1px solid #c3e6cb;\r\n  display: block;\r\n  }\r\n  \r\n  .status-message.error {\r\n  background: #f8d7da;\r\n  color: #721c24;\r\n  border: 1px solid #f5c6cb;\r\n  display: block;\r\n  }\r\n  \r\n  .status-message.processing {\r\n  background: #cce5ff;\r\n  color: #004085;\r\n  border: 1px solid #b8daff;\r\n  display: block;\r\n  }\r\n  \r\n  .progress-wrapper {\r\n  margin-top: 20px;\r\n  display: none;\r\n  }\r\n  \r\n  .progress-wrapper.show {\r\n  display: block;\r\n  }\r\n  \r\n  .progress-bar {\r\n  width: 100%;\r\n  height: 30px;\r\n  background: #e9ecef;\r\n  border-radius: 15px;\r\n  overflow: hidden;\r\n  }\r\n  \r\n  .progress-fill {\r\n  height: 100%;\r\n  background: linear-gradient(90deg, #667eea, #764ba2);\r\n  transition: width 0.3s;\r\n  display: flex;\r\n  align-items: center;\r\n  justify-content: center;\r\n  color: white;\r\n  font-size: 0.9em;\r\n  font-weight: bold;\r\n  }\r\n  \r\n  .info-box {\r\n  background: #f0f4ff;\r\n  border-left: 4px solid #667eea;\r\n  padding: 20px;\r\n  margin: 20px 0;\r\n  border-radius: 8px;\r\n  }\r\n  \r\n  .info-box h4 {\r\n  color: #764ba2;\r\n  margin-bottom: 12px;\r\n  }\r\n  \r\n  .info-box ul {\r\n  list-style: none;\r\n  padding-left: 0;\r\n  }\r\n  \r\n  .info-box li {\r\n  padding: 8px 0;\r\n  color: #555;\r\n  line-height: 1.6;\r\n  }\r\n  \r\n  .info-box li::before {\r\n  content: \"\u2713 \";\r\n  color: #667eea;\r\n  font-weight: bold;\r\n  margin-right: 8px;\r\n  }\r\n  \r\n  .svg-display {\r\n  max-width: 100%;\r\n  max-height: 300px;\r\n  margin: 20px 0;\r\n  padding: 20px;\r\n  background: white;\r\n  border-radius: 8px;\r\n  border: 1px solid #e0e0e0;\r\n  }\r\n  \r\n  .svg-display svg {\r\n  max-width: 100%;\r\n  height: auto;\r\n  }\r\n  \r\n  .file-info {\r\n  background: #f9f9f9;\r\n  padding: 15px;\r\n  border-radius: 8px;\r\n  margin-top: 15px;\r\n  font-size: 0.9em;\r\n  color: #666;\r\n  }\r\n  \r\n  .file-info strong {\r\n  color: #333;\r\n  }\r\n  <\/style>\r\n  \r\n  <div class=\"container\">\r\n    <div class=\"header\">\r\n      <h1>\ud83c\udfac SVG to GIF \u5909\u63db\u30c4\u30fc\u30eb<\/h1>\r\n      <p>SVG\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u3092\u7c21\u5358\u306bGIF\u753b\u50cf\u306b\u5909\u63db<\/p>\r\n    <\/div>\r\n  \r\n    <div class=\"content\">\r\n      <div class=\"column\">\r\n        <h3>\u25bc SVG\u30d5\u30a1\u30a4\u30eb\u3092\u30c9\u30ed\u30c3\u30d7\u3057\u3066\u304f\u3060\u3055\u3044<\/h3>\r\n        <div id=\"endropArea\" class=\"endrop-area\">\r\n          <div class=\"endrop-icon\">\ud83d\udcc1<\/div>\r\n          <div class=\"endrop-text\">SVG\u30d5\u30a1\u30a4\u30eb\u3092\u30c9\u30e9\u30c3\u30b0&\u30c9\u30ed\u30c3\u30d7<\/div>\r\n          <div class=\"drop-subtext\">\u307e\u305f\u306f \u30af\u30ea\u30c3\u30af\u3057\u3066\u9078\u629e<\/div>\r\n          <input type=\"file\" id=\"fileInput\" class=\"file-input\" accept=\".svg,image\/svg+xml\">\r\n        <\/div>\r\n  \r\n        <div id=\"svgInfo\" class=\"file-info\" style=\"display: none;\">\r\n          <strong>\u30d5\u30a1\u30a4\u30eb\u540d:<\/strong> <span id=\"fileName\"><\/span><br>\r\n          <strong>\u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba:<\/strong> <span id=\"fileSize\"><\/span>\r\n        <\/div>\r\n  \r\n        <div class=\"controls\">\r\n          <div class=\"control-group\">\r\n            <label for=\"frameCount\">\r\n              \u30d5\u30ec\u30fc\u30e0\u6570:\r\n              <span class=\"control-value\" id=\"frameCountValue\">20<\/span>\r\n            <\/label>\r\n            <input type=\"range\" id=\"frameCount\" min=\"10\" max=\"60\" value=\"20\">\r\n          <\/div>\r\n  \r\n          <div class=\"control-group\">\r\n            <label for=\"duration\">\r\n              \u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u6642\u9593 (\u79d2):\r\n              <span class=\"control-value\" id=\"durationValue\">3<\/span>\r\n            <\/label>\r\n            <input type=\"range\" id=\"duration\" min=\"1\" max=\"10\" value=\"3\" step=\"0.5\">\r\n          <\/div>\r\n  \r\n          <div class=\"control-group\">\r\n            <label for=\"scale\">\r\n              \u30b9\u30b1\u30fc\u30eb (%):\r\n              <span class=\"control-value\" id=\"scaleValue\">100<\/span>\r\n            <\/label>\r\n            <input type=\"range\" id=\"scale\" min=\"25\" max=\"200\" value=\"100\" step=\"25\">\r\n          <\/div>\r\n  \r\n          <button class=\"button\" id=\"convertButton\" disabled>\u5909\u63db\u958b\u59cb \u00bb<\/button>\r\n        <\/div>\r\n  \r\n        <div class=\"progress-wrapper\" id=\"progressWrapper\">\r\n          <div class=\"progress-bar\">\r\n            <div class=\"progress-fill\" id=\"progressFill\">0%<\/div>\r\n          <\/div>\r\n        <\/div>\r\n  \r\n        <div class=\"status-message\" id=\"statusMessage\"><\/div>\r\n      <\/div>\r\n  \r\n      <div class=\"column\">\r\n        <h3>\u25bc \u5909\u63db\u5f8c\u306eGIF\u753b\u50cf<\/h3>\r\n        <div class=\"preview-area\" id=\"previewArea\">\r\n          <div class=\"preview-placeholder\">\r\n            \u5909\u63db\u3055\u308c\u305fGIF\u304c\u3053\u3053\u306b\u8868\u793a\u3055\u308c\u307e\u3059\r\n          <\/div>\r\n        <\/div>\r\n  \r\n        <button class=\"button download-button\" id=\"downloadButton\">\r\n          \ud83d\udcbe GIF\u753b\u50cf\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\r\n        <\/button>\r\n  \r\n        <div class=\"info-box\">\r\n          <h4>\ud83d\udca1 \u4f7f\u3044\u65b9\u306e\u30d2\u30f3\u30c8<\/h4>\r\n          <ul>\r\n            <li>SVG\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u30d5\u30a1\u30a4\u30eb\u3092\u30c9\u30ed\u30c3\u30d7\u30a8\u30ea\u30a2\u306b\u30c9\u30e9\u30c3\u30b0<\/li>\r\n            <li>\u30d5\u30ec\u30fc\u30e0\u6570\uff1a\u591a\u3044\u307b\u3069\u6ed1\u3089\u304b\u306b\u306a\u308a\u307e\u3059\u304c\u3001\u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba\u304c\u5897\u52a0\u3057\u307e\u3059<\/li>\r\n            <li>\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u6642\u9593\uff1aGIF\u306e\u518d\u751f\u6642\u9593\u3092\u8abf\u6574\u3067\u304d\u307e\u3059<\/li>\r\n            <li>\u30b9\u30b1\u30fc\u30eb\uff1a\u51fa\u529b\u30b5\u30a4\u30ba\u3092\u8abf\u6574\u3067\u304d\u307e\u3059<\/li>\r\n            <li>\u5bfe\u5fdc\u5f62\u5f0f\uff1aCSS\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u3001SMIL\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3<\/li>\r\n          <\/ul>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n  \r\n  <script>\r\n    \/\/\u30b0\u30ed\u30fc\u30d0\u30eb\u5909\u6570\r\n    let svgContent = null;\r\n    let svgFileName = '';\r\n    let frames = [];\r\n  \r\n    \/\/DOM\u8981\u7d20\r\n    const endropArea = document.getElementById('endropArea');\r\n    const fileInput = document.getElementById('fileInput');\r\n    const convertButton = document.getElementById('convertButton');\r\n    const downloadButton = document.getElementById('downloadButton');\r\n    const statusMessage = document.getElementById('statusMessage');\r\n    const progressWrapper = document.getElementById('progressWrapper');\r\n    const progressFill = document.getElementById('progressFill');\r\n    const previewArea = document.getElementById('previewArea');\r\n    const svgInfo = document.getElementById('svgInfo');\r\n    const fileName = document.getElementById('fileName');\r\n    const fileSize = document.getElementById('fileSize');\r\n  \r\n    \/\/\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u8981\u7d20\r\n    const frameCountSlider = document.getElementById('frameCount');\r\n    const durationSlider = document.getElementById('duration');\r\n    const scaleSlider = document.getElementById('scale');\r\n  \r\n    \/\/\u30b9\u30e9\u30a4\u30c0\u30fc\u306e\u5024\u8868\u793a\u66f4\u65b0\r\n    frameCountSlider.addEventListener('input', (e) => {\r\n      document.getElementById('frameCountValue').textContent = e.target.value;\r\n    });\r\n  \r\n    durationSlider.addEventListener('input', (e) => {\r\n      document.getElementById('durationValue').textContent = e.target.value;\r\n    });\r\n  \r\n    scaleSlider.addEventListener('input', (e) => {\r\n      document.getElementById('scaleValue').textContent = e.target.value;\r\n    });\r\n  \r\n    \/\/\u30c9\u30e9\u30c3\u30b0&\u30c9\u30ed\u30c3\u30d7\u30a4\u30d9\u30f3\u30c8\r\n    endropArea.addEventListener('click', () => fileInput.click());\r\n  \r\n    endropArea.addEventListener('dragover', (e) => {\r\n      e.preventDefault();\r\n      endropArea.classList.add('dragover');\r\n    });\r\n  \r\n    endropArea.addEventListener('dragleave', () => {\r\n      endropArea.classList.remove('dragover');\r\n    });\r\n  \r\n    endropArea.addEventListener('drop', (e) => {\r\n      e.preventDefault();\r\n      endropArea.classList.remove('dragover');\r\n      const file = e.dataTransfer.files[0];\r\n      if (file) handleFile(file);\r\n    });\r\n  \r\n    fileInput.addEventListener('change', (e) => {\r\n      const file = e.target.files[0];\r\n      if (file) handleFile(file);\r\n    });\r\n  \r\n    \/\/\u30d5\u30a1\u30a4\u30eb\u51e6\u7406\r\n    function handleFile(file) {\r\n      if (!file || !file.type.includes('svg')) {\r\n        showStatus('SVG\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044', 'error');\r\n        return;\r\n      }\r\n  \r\n      svgFileName = file.name.replace('.svg', '');\r\n      fileName.textContent = file.name;\r\n      fileSize.textContent = formatFileSize(file.size);\r\n      svgInfo.style.display = 'block';\r\n  \r\n      const reader = new FileReader();\r\n      reader.onload = (e) => {\r\n        svgContent = e.target.result;\r\n        endropArea.classList.add('has-file');\r\n        endropArea.innerHTML = `\r\n  <div class=\"svg-display\">${svgContent}<\/div>\r\n  <div class=\"drop-subtext\">\u65b0\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u3092\u30c9\u30ed\u30c3\u30d7\u3057\u3066\u5909\u66f4<\/div>\r\n  `;\r\n        convertButton.disabled = false;\r\n        showStatus('SVG\u30d5\u30a1\u30a4\u30eb\u304c\u8aad\u307f\u8fbc\u307e\u308c\u307e\u3057\u305f', 'success');\r\n      };\r\n      reader.readAsText(file);\r\n    }\r\n  \r\n    \/\/\u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\r\n    function formatFileSize(bytes) {\r\n      if (bytes < 1024) return bytes + ' B';\r\n      if (bytes < 1048576) return Math.round(bytes \/ 1024) + ' KB';\r\n      return Math.round(bytes \/ 1048576 * 10) \/ 10 + ' MB';\r\n    }\r\n  \r\n    \/\/\u5909\u63db\u30dc\u30bf\u30f3\u30af\u30ea\u30c3\u30af\r\n    convertButton.addEventListener('click', async () => {\r\n      if (!svgContent) return;\r\n  \r\n      convertButton.disabled = true;\r\n      showStatus('\u5909\u63db\u51e6\u7406\u4e2d...\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044', 'processing');\r\n      progressWrapper.classList.add('show');\r\n      downloadButton.classList.remove('show');\r\n      frames = [];\r\n  \r\n      try {\r\n        await convertSvgToFrames();\r\n        showStatus('\u5909\u63db\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f\uff01', 'success');\r\n      } catch (error) {\r\n        showStatus('\u5909\u63db\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: ' + error.message, 'error');\r\n        console.error(error);\r\n      } finally {\r\n        convertButton.disabled = false;\r\n        progressWrapper.classList.remove('show');\r\n      }\r\n    });\r\n  \r\n    \/\/SVG\u3092\u30d5\u30ec\u30fc\u30e0\u306b\u5909\u63db\r\n    async function convertSvgToFrames() {\r\n      const frameCount = parseInt(frameCountSlider.value);\r\n      const duration = parseFloat(durationSlider.value);\r\n      const scale = parseInt(scaleSlider.value) \/ 100;\r\n  \r\n      \/\/SVG\u306e\u30b5\u30a4\u30ba\u3092\u53d6\u5f97\r\n      const parser = new DOMParser();\r\n      const doc = parser.parseFromString(svgContent, 'image\/svg+xml');\r\n      const svgElement = doc.querySelector('svg');\r\n  \r\n      let width = 500;\r\n      let height = 500;\r\n  \r\n      if (svgElement) {\r\n        const viewBox = svgElement.getAttribute('viewBox');\r\n        if (viewBox) {\r\n          const parts = viewBox.split(' ');\r\n          width = parseFloat(parts[2]) * scale;\r\n          height = parseFloat(parts[3]) * scale;\r\n        } else {\r\n          width = (parseFloat(svgElement.getAttribute('width')) || 500) * scale;\r\n          height = (parseFloat(svgElement.getAttribute('height')) || 500) * scale;\r\n        }\r\n      }\r\n  \r\n      \/\/\u30ad\u30e3\u30f3\u30d0\u30b9\u4f5c\u6210\r\n      const canvas = document.createElement('canvas');\r\n      canvas.width = width;\r\n      canvas.height = height;\r\n      const ctx = canvas.getContext('2d');\r\n  \r\n      \/\/\u5404\u30d5\u30ec\u30fc\u30e0\u3092\u751f\u6210\r\n      for (let i = 0; i < frameCount; i++) {\r\n        const progress = i \/ (frameCount - 1);\r\n        updateProgress(Math.round(progress * 100));\r\n  \r\n        \/\/SVG\u3092\u6642\u9593\u8ef8\u4e0a\u3067\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\r\n        const frameData = await renderSvgFrame(svgContent, progress, canvas, ctx, width, height);\r\n        frames.push(frameData);\r\n  \r\n        await delay(50); \/\/\u51e6\u7406\u3092\u5206\u6563\r\n      }\r\n  \r\n      \/\/\u30d7\u30ec\u30d3\u30e5\u30fc\u8868\u793a\uff08\u6700\u521d\u306e\u30d5\u30ec\u30fc\u30e0\uff09\r\n      if (frames.length > 0) {\r\n        displayPreview(frames, duration, width, height);\r\n        setupDownload(frames, duration, width, height);\r\n      }\r\n    }\r\n  \r\n    \/\/SVG\u30d5\u30ec\u30fc\u30e0\u3092\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\r\n    async function renderSvgFrame(svg, progress, canvas, ctx, width, height) {\r\n      return new Promise((resolve, reject) => {\r\n        \/\/SVG\u306e\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u6642\u9593\u3092\u8abf\u6574\r\n        const modifiedSvg = updateSvgForProgress(svg, progress);\r\n  \r\n        const img = new Image();\r\n        const blob = new Blob([modifiedSvg], { type: 'image\/svg+xml' });\r\n        const url = URL.createObjectURL(blob);\r\n  \r\n        img.onload = () => {\r\n          ctx.clearRect(0, 0, width, height);\r\n          ctx.fillStyle = 'white';\r\n          ctx.fillRect(0, 0, width, height);\r\n          ctx.drawImage(img, 0, 0, width, height);\r\n  \r\n          const imageData = canvas.toDataURL('image\/png');\r\n          URL.revokeObjectURL(url);\r\n          resolve(imageData);\r\n        };\r\n  \r\n        img.onerror = () => {\r\n          URL.revokeObjectURL(url);\r\n          reject(new Error('\u30d5\u30ec\u30fc\u30e0\u306e\u751f\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f'));\r\n        };\r\n  \r\n        img.src = url;\r\n      });\r\n    }\r\n  \r\n    \/\/SVG\u306e\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u9032\u884c\u72b6\u614b\u3092\u66f4\u65b0\r\n    function updateSvgForProgress(svg, progress) {\r\n      const parser = new DOMParser();\r\n      const doc = parser.parseFromString(svg, 'image\/svg+xml');\r\n  \r\n      \/\/CSS\u5909\u6570\u3092\u4f7f\u7528\u3057\u305f\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u5236\u5fa1\r\n      const svgElement = doc.querySelector('svg');\r\n      if (svgElement) {\r\n        svgElement.style.setProperty('--progress', progress);\r\n        svgElement.style.setProperty('--frame', progress);\r\n  \r\n        \/\/\u30b9\u30bf\u30a4\u30eb\u30bf\u30b0\u3092\u8ffd\u52a0\u3057\u3066\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u3092\u5236\u5fa1\r\n        const styleElement = doc.createElement('style');\r\n        styleElement.textContent = `\r\n  * {\r\n  animation-delay: -${progress * 10}s !important;\r\n  animation-play-state: paused !important;\r\n  }\r\n  `;\r\n        svgElement.appendChild(styleElement);\r\n      }\r\n  \r\n      \/\/SMIL\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u306e\u6642\u9593\u3092\u8a2d\u5b9a\r\n      const animateElements = doc.querySelectorAll('animate, animateTransform, animateMotion, set');\r\n      animateElements.forEach(element => {\r\n        const dur = element.getAttribute('dur') || '1s';\r\n        const durValue = parseDuration(dur);\r\n        const time = durValue * progress;\r\n        element.setAttribute('begin', `-${time}s`);\r\n        element.setAttribute('fill', 'freeze');\r\n      });\r\n  \r\n      return new XMLSerializer().serializeToString(doc);\r\n    }\r\n  \r\n    \/\/\u6642\u9593\u306e\u30d1\u30fc\u30b9\r\n    function parseDuration(dur) {\r\n      if (dur.endsWith('s')) {\r\n        return parseFloat(dur);\r\n      } else if (dur.endsWith('ms')) {\r\n        return parseFloat(dur) \/ 1000;\r\n      }\r\n      return parseFloat(dur);\r\n    }\r\n  \r\n    \/\/\u30d7\u30ec\u30d3\u30e5\u30fc\u8868\u793a\uff08\u7c21\u6613\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\uff09\r\n    function displayPreview(frames, duration, width, height) {\r\n      const canvas = document.createElement('canvas');\r\n      canvas.width = width;\r\n      canvas.height = height;\r\n      const ctx = canvas.getContext('2d');\r\n  \r\n      let currentFrame = 0;\r\n      const frameDelay = (duration * 1000) \/ frames.length;\r\n  \r\n      const animate = () => {\r\n        const img = new Image();\r\n        img.onload = () => {\r\n          ctx.clearRect(0, 0, width, height);\r\n          ctx.drawImage(img, 0, 0);\r\n        };\r\n        img.src = frames[currentFrame];\r\n  \r\n        currentFrame = (currentFrame + 1) % frames.length;\r\n      };\r\n  \r\n      setInterval(animate, frameDelay);\r\n  \r\n      previewArea.innerHTML = '';\r\n      previewArea.appendChild(canvas);\r\n    }\r\n  \r\n    \/\/\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u8a2d\u5b9a\r\n    function setupDownload(frames, duration, width, height) {\r\n      downloadButton.classList.add('show');\r\n      downloadButton.onclick = () => {\r\n        showStatus('GIF\u751f\u6210\u4e2d...\u3053\u306e\u51e6\u7406\u306b\u306f\u6642\u9593\u304c\u304b\u304b\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059', 'processing');\r\n  \r\n        \/\/\u30d5\u30ec\u30fc\u30e0\u30c7\u30fc\u30bf\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u7528\u306b\u5909\u63db\r\n        \/\/\u6ce8\u610f: \u5b9f\u969b\u306eGIF\u751f\u6210\u306b\u306f\u30b5\u30fc\u30d0\u30fc\u30b5\u30a4\u30c9\u51e6\u7406\u304c\u5fc5\u8981\u3067\u3059\r\n        \/\/\u3053\u3053\u3067\u306f\u30d5\u30ec\u30fc\u30e0\u753b\u50cf\u306eZIP\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u63d0\u4f9b\r\n        downloadFramesAsZip(frames);\r\n      };\r\n    }\r\n  \r\n    \/\/\u30d5\u30ec\u30fc\u30e0\u3092ZIP\u3068\u3057\u3066\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\uff08\u4ee3\u66ff\u6848\uff09\r\n    function downloadFramesAsZip(frames) {\r\n      \/\/\u7c21\u6613\u7684\u306a\u5b9f\u88c5\uff1a\u6700\u521d\u306e\u30d5\u30ec\u30fc\u30e0\u3092PNG\u3068\u3057\u3066\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\r\n      const link = document.createElement('a');\r\n      link.download = `${svgFileName}_frame.png`;\r\n      link.href = frames[0];\r\n      link.click();\r\n  \r\n      showStatus(`\u30d5\u30ec\u30fc\u30e0\u753b\u50cf\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u307e\u3057\u305f\u3002\u5b8c\u5168\u306aGIF\u5909\u63db\u306b\u306f\u30b5\u30fc\u30d0\u30fc\u30b5\u30a4\u30c9\u51e6\u7406\u304c\u5fc5\u8981\u3067\u3059\u3002`, 'success');\r\n    }\r\n  \r\n    \/\/\u9032\u6357\u66f4\u65b0\r\n    function updateProgress(percent) {\r\n      progressFill.style.width = percent + '%';\r\n      progressFill.textContent = percent + '%';\r\n    }\r\n  \r\n    \/\/\u30b9\u30c6\u30fc\u30bf\u30b9\u8868\u793a\r\n    function showStatus(message, type) {\r\n      statusMessage.className = 'status-message ' + type;\r\n      statusMessage.textContent = message;\r\n  \r\n      if (type !== 'processing') {\r\n        setTimeout(() => {\r\n          statusMessage.className = 'status-message';\r\n        }, 5000);\r\n      }\r\n    }\r\n  \r\n    \/\/\u9045\u5ef6\u95a2\u6570\r\n    function delay(ms) {\r\n      return new Promise(resolve => setTimeout(resolve, ms));\r\n    }\r\n  <\/script>","protected":false},"excerpt":{"rendered":"\ud83c\udfac SVG to GIF \u5909\u63db\u30c4\u30fc\u30eb SVG\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u3092\u7c21\u5358\u306bGIF\u753b\u50cf\u306b\u5909\u63db \u25bc SVG\u30d5\u30a1\u30a4\u30eb\u3092\u30c9\u30ed\u30c3\u30d7\u3057\u3066\u304f\u3060\u3055\u3044 \ud83d\udcc1 SVG\u30d5\u30a1\u30a4\u30eb\u3092\u30c9\u30e9\u30c3\u30b0&#038;\u30c9\u30ed\u30c3\u30d7 \u307e\u305f\u306f \u30af\u30ea\u30c3\u30af\u3057\u3066\u9078\u629e \u30d5\u30a1\u30a4\u30eb\u540d: \u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba[...]","protected":false},"author":1,"featured_media":0,"parent":173,"menu_order":22,"comment_status":"closed","ping_status":"closed","template":"page\/page-converter.php","meta":{"footnotes":""},"categories":[21],"tags":[],"class_list":{"0":"post-9036","1":"page","2":"type-page","3":"status-publish","5":"category-tool"},"_links":{"self":[{"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/pages\/9036","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/comments?post=9036"}],"version-history":[{"count":5,"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/pages\/9036\/revisions"}],"predecessor-version":[{"id":9041,"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/pages\/9036\/revisions\/9041"}],"up":[{"embeddable":true,"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/pages\/173"}],"wp:attachment":[{"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/media?parent=9036"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/categories?post=9036"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-plus.jp\/gp\/wp-json\/wp\/v2\/tags?post=9036"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}