2017-02-09 9 views
0

EDIT: Создана внешний шаблон для моей директивыЭкспорт SVG в PNG с помощью d3js-Wordcloud угловых Директив

Я хотел бы реализовать простую функцию загрузки/экспорта, которая будет конвертировать и сохранить вынесенное SVG слово облако как png в моем приложении Angular.

Я использую генератор облаков слов d3, сделанный Джейсоном Дэвисом и упрощенный сценарий Жюльена Рено.

Я пытаюсь добавить простой функции экспорта, используя копи-SVG-как-в-изображение экспорта функции iweczek в (http://techslides.com/save-svg-as-an-image), но где-то я что-то отсутствует.

Это моя Угловая Директива Wordcloud, в том числе функции экспорта в нижней части (scope.exportToPNG):

'use strict'; 

/** 
* @ngdoc: function 
* @name: portalDashboardApp.directive:ogWordCloud 
* @description: Word Cloud Generator based on the d3 word cloud generator done by Jason Davies and a simplified script by Julien Renaux 
* Directive of the portalDashboardApp 
*/ 

angular.module('portalDashboardApp') 
    .directive('ogWordCloud', function() { 
     return { 
      restrict: 'E', 
      replace: true, 
      templateUrl: './socialMedia.module/socialMedia.templates/WordCloudTemplate.html', 
      scope: { 
       words: '=' 
      }, 
      link: function (scope) { 

       var fill = d3.scale.category20b(); 

       var w = window.innerWidth - 238, 
       h = 400; 

       var max, 
       fontSize; 

       var layout = d3.layout.cloud() 
       .timeInterval(Infinity) 
       .size([w, h]) 
       .fontSize(function (d) { 
        return fontSize(+d.value); 
       }) 
       .text(function (d) { 
        return d.key; 
       }) 
       .on("end", draw); 

       var svg = d3.select("#wordCloudVisualisation").append("svg") 
       .attr("width", w) 
       .attr("height", h) 
       .attr("xmlns", 'http://www.w3.org/2000/svg') 
       .attr("xmlns:xlink", 'http://www.w3.org/1999/xlink') 
       .attr("version", '1.1') 
       .attr("id", "wordCloudSVG"); 

       var wordCloudVisualisation = svg.append("g").attr("transform", "translate(" + [w >> 1, h >> 1] + ")"); 

       update(); 

       window.onresize = function (event) { 
        update(); 
       }; 

       var tags = []; 

       scope.$watch('words', function() { 
        tags = scope.words; 
       }, true); 

       function draw(data, bounds) { 
        var w = window.innerWidth - 238, 
        h = 400; 

        svg.attr("width", w).attr("height", h); 

        var scale = bounds ? Math.min(
        w/Math.abs(bounds[1].x - w/2), 
        w/Math.abs(bounds[0].x - w/2), 
        h/Math.abs(bounds[1].y - h/2), 
        h/Math.abs(bounds[0].y - h/2))/2 : 1; 

        var text = wordCloudVisualisation.selectAll("text") 
        .data(data, function (d) { 
         return d.text.toLowerCase(); 
        }); 
        text.transition() 
        .duration(1000) 
        .attr("transform", function (d) { 
         return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; 
        }) 
        .style("font-size", function (d) { 
         return d.size + "px"; 
        }); 
        text.enter().append("text") 
        .attr("text-anchor", "middle") 
        .attr("transform", function (d) { 
         return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; 
        }) 
        .style("font-size", function (d) { 
         return d.size + "px"; 
        }) 
        .style("opacity", 1e-6) 
        .transition() 
        .duration(1000) 
        .style("opacity", 1); 
        text.style("font-family", function (d) { 
         return d.font; 
        }) 
        .style("fill", function (d) { 
         return fill(d.text.toLowerCase()); 
        }) 
        .text(function (d) { 
         return d.text; 
        }); 

        wordCloudVisualisation.transition().attr("transform", "translate(" + [w >> 1, h >> 1] + ")scale(" + scale + ")"); 
       } 

       function update() { 
        layout.font('impact').spiral('archimedean'); 
        fontSize = d3.scale['sqrt']().range([10, 100]); 
        if (scope.words.length) { 
         fontSize.domain([+scope.words[scope.words.length - 1].value || 1, +scope.words[0].value]); 
        } 
        layout.stop().words(scope.words).start(); 
       } 

////////////////////////////////////////////////////////////////// 

       scope.exportToPNG = function() { 

        var html = d3.select("svg") //svg 
         .attr("version", 1.1) 
         .attr("xmlns", "http://www.w3.org/2000/svg") 
         .node().parentNode.innerHTML; 

        var imgsrc = 'data:image/svg+xml;base64,' + btoa(html); 
        var img = '<img src="' + imgsrc + '">'; 
        d3.select("#svgdataurl").html(img); 


        var canvas = document.querySelector("canvas"), 
         context = canvas.getContext("2d"); 

        var image = new Image; 
        image.src = imgsrc; 
        image.onload = function() { 
         context.drawImage(image, 0, 0); 

         var canvasdata = canvas.toDataURL("image/png"); 

         var pngimg = '<img src="' + canvasdata + '">'; 
         d3.select("#pngdataurl").html(pngimg); 

         var a = document.createElement("a"); 
         a.download = "sample.png"; 
         a.href = canvasdata; 
         a.click(); 
        }; 
       } 
      } 
     }; 
    }); 

Это мой шаблон директива:

<div id="wordCloud"> 
    <button class="basicButton" ng-click="exportToPNG()">Export to .PNG</button> 
    <div id="wordCloudVisualisation"></div> 
    <canvas id="canvas"></canvas> 
    <h2>svgdataurl</h2> 
    <div id="svgdataurl"></div> 
    <h2>pngdataurl</h2> 
    <div id="pngdataurl"></div> 
</div> 

EDIT: Как и в случае с кодом, генерируется сломанное изображение (например, когда изображение отсутствует у заполнителя на веб-сайт) в Chrome. В IE он создает изображение в моем «svgdataurl», но бомбит. Я считаю, что это не , совместимый с IE.

Буду признателен за помощь!

ответ

2

я смог исправить решить свои проблемы, благодаря следующим должностям:

Save inline SVG as JPEG/PNG/SVG

https://gist.github.com/gustavohenke/9073132

Вот мой полный рабочий раствор:

Моей Угловая директива :

'use strict'; 

/** 
* @ngdoc: function 
* @name: portalDashboardApp.directive:ogWordCloud 
* @description: Word Cloud Generator based on the d3 word cloud generator done by Jason Davies and a simplified script by Julien Renaux 
* Directive of the portalDashboardApp 
*/ 

angular.module('portalDashboardApp') 
    .directive('ogWordCloud', function() { 
     return { 
      restrict: 'E', 
      replace: true, 
      templateUrl: './socialMedia.module/socialMedia.templates/WordCloudTemplate.html', 
      scope: { 
       words: '=' 
      }, 
      link: function (scope) { 

       var fill = d3.scale.category20b(); 

       var w = window.innerWidth - 238, 
       h = 400; 

       var max, 
       fontSize; 

       var layout = d3.layout.cloud() 
       .timeInterval(Infinity) 
       .size([w, h]) 
       .fontSize(function (d) { 
        return fontSize(+d.value); 
       }) 
       .text(function (d) { 
        return d.key; 
       }) 
       .on("end", draw); 

       var svg = d3.select("#wordCloudVisualisation").append("svg") 
       .attr("width", w) 
       .attr("height", h) 
       .attr("xmlns", 'http://www.w3.org/2000/svg') 
       .attr("xmlns:xlink", 'http://www.w3.org/1999/xlink') 
       .attr("version", '1.1') 
       .attr("id", "wordCloudSVG"); 

       var wordCloudVisualisation = svg.append("g").attr("transform", "translate(" + [w >> 1, h >> 1] + ")"); 

       update(); 

       window.onresize = function (event) { 
        update(); 
       }; 

       var tags = []; 

       scope.$watch('words', function() { 
        tags = scope.words; 
       }, true); 

       function draw(data, bounds) { 
        var w = window.innerWidth - 238, 
        h = 400; 

        svg.attr("width", w).attr("height", h); 

        var scale = bounds ? Math.min(
        w/Math.abs(bounds[1].x - w/2), 
        w/Math.abs(bounds[0].x - w/2), 
        h/Math.abs(bounds[1].y - h/2), 
        h/Math.abs(bounds[0].y - h/2))/2 : 1; 

        var text = wordCloudVisualisation.selectAll("text") 
        .data(data, function (d) { 
         return d.text.toLowerCase(); 
        }); 
        text.transition() 
        .duration(1000) 
        .attr("transform", function (d) { 
         return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; 
        }) 
        .style("font-size", function (d) { 
         return d.size + "px"; 
        }); 
        text.enter().append("text") 
        .attr("text-anchor", "middle") 
        .attr("transform", function (d) { 
         return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; 
        }) 
        .style("font-size", function (d) { 
         return d.size + "px"; 
        }) 
        .style("opacity", 1e-6) 
        .transition() 
        .duration(1000) 
        .style("opacity", 1); 
        text.style("font-family", function (d) { 
         return d.font; 
        }) 
        .style("fill", function (d) { 
         return fill(d.text.toLowerCase()); 
        }) 
        .text(function (d) { 
         return d.text; 
        }); 

        wordCloudVisualisation.transition().attr("transform", "translate(" + [w >> 1, h >> 1] + ")scale(" + scale + ")"); 
       } 

       function update() { 
        layout.font('impact').spiral('archimedean'); 
        fontSize = d3.scale['sqrt']().range([10, 100]); 
        if (scope.words.length) { 
         fontSize.domain([+scope.words[scope.words.length - 1].value || 1, +scope.words[0].value]); 
        } 
        layout.stop().words(scope.words).start(); 
       } 

       scope.exportToPNG2 = function() { 

        var svg = document.querySelector('#wordCloudSVG'); //svg 
        var canvas = document.createElement("canvas"); 

        var svgSize = svg.getBoundingClientRect(); 
        canvas.width = svgSize.width; 
        canvas.height = svgSize.height; 

        var ctx = canvas.getContext('2d'); 
        var data = new XMLSerializer().serializeToString(svg); 

        var DOMURL = window.URL || window.webkitURL || window; 

        var img = new Image(); 
        var svgBlob = new Blob([data], { type: 'image/svg+xml;charset=utf-8' }); 
        var url = DOMURL.createObjectURL(svgBlob); 

        img.onload = function() { 
         ctx.drawImage(img, 0, 0); 
         DOMURL.revokeObjectURL(url); 

         var imgURI = canvas 
          .toDataURL('image/png') 
          .replace('image/png', 'image/octet-stream'); 

         triggerDownload(imgURI); 
        }; 

        img.src = url; 
       } 

       function triggerDownload(imgURI) { 
        var evt = new MouseEvent('click', { 
         view: window, 
         bubbles: false, 
         cancelable: true 
        }); 

        var a = document.createElement('a'); 
        a.setAttribute('download', 'MY_COOL_IMAGE.png'); 
        a.setAttribute('href', imgURI); 
        a.setAttribute('target', '_blank'); 

        a.dispatchEvent(evt); 
       } 

      } 
     }; 
    }); 

Мой шаблон директиву:

<div id="wordCloud"> 
    <button class="basicButton" ng-click="exportToPNG2()">Export to .PNG</button> 
    <div id="wordCloudVisualisation"></div> 
    <canvas id="WordCloudCanvas"></canvas> 
</div> 

Я надеюсь, что это помогает кто-то другой!

0

Разделы div #svgdataurl и #pngdataurl уже существуют вне вашей директивы? Если нет, вы должны включить их в свой шаблон директивы. В приведенном ниже примере они уже присутствуют на странице, не созданной функцией click.

Вы также можете посмотреть аналогичный инструмент, выпущенный Майком Бостоком, который использует canvas.toBlob(): https://github.com/mbostock/svjimmy/blob/master/index.js.

+0

Благодарим за отзыв! Я ценю помощь. Вы увидите, что мой шаблон директивы фактически является частью моей директивы. У меня нет внешнего файла шаблона.'template: '

« Не могли бы вы дать мне предложения по добавлению недостающих тегов? – onmyway

+0

Я создал внешний шаблон для моей директивы. См. Обновленный вопрос. – onmyway

 Смежные вопросы

  • Нет связанных вопросов^_^