Копировать SVG в буфер обмена как изображение

#javascript #image #svg #clipboard #copy-paste

#javascript #изображение #svg #буфер обмена #копировать-вставить

Вопрос:

Я работаю над приложением, в котором я хочу предоставить кнопку копирования для копирования svg в виде изображения в буфер обмена, которое можно вставить в другие места.

Я пытался использовать clipboard API, но у него много ограничений безопасности, более того, он, похоже, не работает с http и работает только с png.

Я также попробовал document.execCommand('copy') , создав div с изображением, но у меня это сработало только в MS Word, но не в slack или stack overflow (не уверен, почему).

Я хочу воспроизвести поведение опции копирования изображения контекстного меню правой кнопки мыши Chrome / Firefox с помощью Javascript.

Есть ли какой-то способ, которым это возможно? Я открыт для всех идей. Спасибо!

Комментарии:

1. Было бы неплохо иметь некоторый код для обработки. В зависимости от ваших потребностей, вы можете попробовать нарисовать svg внутреннюю часть a canvas с помощью javascript, как в этом примере: tutorialspoint.com/How-to-draw-an-SVG-file-on-an-HTML5-canvas

2. Я изучил вариант написания canvas, но как скопировать это как изображение в буфер обмена?

3. Извините, меня смутило предложение о щелчке правой кнопкой мыши. Для вашей проблемы я не вижу способа обойти API буфера обмена. execCommand Стратегия экспортирует не изображение, а HTML-код. Вот почему он работает в Word, но не в процессорах обработки изображений. Вы можете найти полезные примеры на developer.mozilla.org/en-US/docs/Web/API/Clipboard/write , но с оговорками. Я боюсь, что это головная боль, а не переносимая.

4. Спасибо @vqf. Есть идеи, как это делает chrome / firefox? Я сомневаюсь, что они, вероятно, используют некоторые API, отличные от тех, которые предоставлены в JS. Любые идеи или ссылки были бы замечательными.

5. Какое изображение вы ожидаете, что оно будет копировать / вставлять? Изображение SVG? Тогда разметка, которую вы имеете, — это изображение svg. Растровое изображение? Если да, то в каких размерах и почему? В каком состоянии? (помните, что svg-изображения могут быть анимированы с помощью SMIL или CSS и даже интерактивны)

Ответ №1:

Просто несколько указателей, а не фактический ответ. Я создал локальный пример, используя информацию в комментариях:

 <!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" style="border:2px solid green;" width="300" height="300"> 
</canvas>
      <script>
        function copyCanvas() {
          let canvas = document.getElementById('myCanvas');
          canvas.toBlob(function (blob) {
            let data = [new ClipboardItem({ [blob.type]: blob })];

            navigator.clipboard.write(data).then(function () {
              alert('Copied');
            }, function (err) {
              alert('Not copied');
            })
          });
        }
  
         let canvas = document.getElementById('myCanvas');
         let ctx = canvas.getContext('2d');
         var data = `<svg xmlns="http://www.w3.org/2000/svg" width="300"
         height="200">'  
            '<foreignObject width="100%" height="100%">'  
               '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:50px">'  
                  'Simply Easy '  
                  '<span style="color:blue;">'  
                  'Learning</span>'  
               '</div>'  
            '</foreignObject>'  
         '</svg>`;
         var DOMURL = window.URL || window.webkitURL || window;
         var img1 = new Image();
         var svg = new Blob([data], {type: 'image/svg xml'});
         var url = DOMURL.createObjectURL(svg);
         img1.onload = function() {
            ctx.drawImage(img1, 25, 70);
            DOMURL.revokeObjectURL(url);
         }
         img1.src = url;
         setTimeout(copyCanvas, 3000);
      </script>
</body>
</html>
  

Это не работает, но это может быть началом. Если copyCanvas() вызывается напрямую, без setTimeout , я получаю черную картинку с правильным размером в Chrome. Я думаю, это означает, что холст все еще не нарисован. С задержкой на холсте отображается изображение, но я получаю сообщение об ошибке, в котором говорится, что оно не может быть преобразовано, toBlob поскольку оно испорчено. Это объясняется здесь . Вы можете избежать этой проблемы, если сможете установить политику CORS на своем сервере. Я все еще не уверен в переносимости решения.

Ответ №2:

Вы можете просто скопировать код Base64 после символа ‘,’ в end ( PHN2ZyB4bWxu...4= ) и преобразовать его в SVG с помощью любых сервисов (например, base64.guru), а затем скопировать результат в буфер обмена в виде изображения.

 data:image/svg xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIiB3aWR0aD0iNDQ4IiBoZWlnaHQ9IjUxMiI PHBhdGggZmlsbD0iIzNhNWI4NyIgZD0iTTAgNDY0YzAgMjYuNSAyMS41IDQ4IDQ4IDQ4aDM1MmMyNi41IDAgNDgtMjEuNSA0OC00OFYxOTJIMHYyNzJ6bTMyMC0xOTZjMC02LjYgNS40LTEyIDEyLTEyaDQwYzYuNiAwIDEyIDUuNCAxMiAxMnY0MGMwIDYuNi01LjQgMTItMTIgMTJoLTQwYy02LjYgMC0xMi01LjQtMTItMTJ2LTQwem0wIDEyOGMwLTYuNiA1LjQtMTIgMTItMTJoNDBjNi42IDAgMTIgNS40IDEyIDEydjQwYzAgNi42LTUuNCAxMi0xMiAxMmgtNDBjLTYuNiAwLTEyLTUuNC0xMi0xMnYtNDB6TTE5MiAyNjhjMC02LjYgNS40LTEyIDEyLTEyaDQwYzYuNiAwIDEyIDUuNCAxMiAxMnY0MGMwIDYuNi01LjQgMTItMTIgMTJoLTQwYy02LjYgMC0xMi01LjQtMTItMTJ2LTQwem0wIDEyOGMwLTYuNiA1LjQtMTIgMTItMTJoNDBjNi42IDAgMTIgNS40IDEyIDEydjQwYzAgNi42LTUuNCAxMi0xMiAxMmgtNDBjLTYuNiAwLTEyLTUuNC0xMi0xMnYtNDB6TTY0IDI2OGMwLTYuNiA1LjQtMTIgMTItMTJoNDBjNi42IDAgMTIgNS40IDEyIDEydjQwYzAgNi42LTUuNCAxMi0xMiAxMkg3NmMtNi42IDAtMTItNS40LTEyLTEydi00MHptMCAxMjhjMC02LjYgNS40LTEyIDEyLTEyaDQwYzYuNiAwIDEyIDUuNCAxMiAxMnY0MGMwIDYuNi01LjQgMTItMTIgMTJINzZjLTYuNiAwLTEyLTUuNC0xMi0xMnYtNDB6TTQwMCA2NGgtNDhWMTZjMC04LjgtNy4yLTE2LTE2LTE2aC0zMmMtOC44IDAtMTYgNy4yLTE2IDE2djQ4SDE2MFYxNmMwLTguOC03LjItMTYtMTYtMTZoLTMyYy04LjggMC0xNiA3LjItMTYgMTZ2NDhINDhDMjEuNSA2NCAwIDg1LjUgMCAxMTJ2NDhoNDQ4di00OGMwLTI2LjUtMjEuNS00OC00OC00OHoiPjwvcGF0aD48L3N2Zz4=