0

Currently I'm working on a small project. At this stage I have several word cloud SVGs with the help of d3.js word cloud.

Now I want to make the SVG's 'text' element draggable with JQuery UI so that user can drag the text element and then drop it on certain area (say a droppable div).

But after several attempts, it seems that JQuery-UI is not that compatible with SVG. I've compared several similar questions and tried on my own code, but none of them worked. The most up-voted answer of this question is very close to what I want. The text element is draggable, but when I click the element, it doesn't appear in the right position and it would appear elsewhere. And also the element cannot be dragged out of its SVG container.

Here's my JS code:

var fill = d3.scale.category20();

function draw(words) {
  d3.select('#wordCloud').append("svg")
      .attr("width", 600)
      .attr("height", 600)
    .append("g")
      .attr("transform", "translate(300,300)")
    .selectAll("text")
      .data(words)
    .enter().append("text")
      .style("font-size", function(d) { return d.size + "px"; })
      .style("font-family", "Impact")
      .style("fill", function(d, i) { return fill(i); })
      .attr("text-anchor", "middle")
      .attr("transform", function(d) {
        return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
      })
      .text(function(d) { return d.text; });
}

wordCloudData.map((model) => {
  let modelName = model.modelName;
  let wordsArray = model.specArray;
  var $title = $('<h4></h4>').text(modelName);
  $('#wordCloud').append($title);

  d3.layout.cloud().size([600, 600])
      .words(wordsArray.map(function(d) {
        return {text: d, size: 10 + Math.random() * 90};
      }))
      // .rotate(function() { return ~~(Math.random() * 2) * 90; })
      .font("Impact")
      .fontSize(function(d) { return d.size * 0.6; })
      .on("end", draw)
      .start();
});


$(document).ready(function() {
  let wordCloudCount = $('#wordCloud svg').length;
  let svgArray = $('#wordCloud svg').clone();
  let titleArray = $('#wordCloud h4').clone();
  for (let i = 0; i < wordCloudCount; i++) {
    let $wordCloudDiv = $('<div></div>').attr('class', 'wordCloud');
    let $title = titleArray[i];
    let $svg = svgArray[i];
    $wordCloudDiv.append($title);
    $wordCloudDiv.append($svg);
    $('#wordCloudFinal').append($wordCloudDiv);
  }
  $('#wordCloud').hide();

  $('text')
  .draggable()
  .bind('mousedown', function(event, ui){
    $(event.target.parentElement).append( event.target );
  })
  .bind('drag', function(event, ui){
    event.target.setAttribute('x', ui.position.left);
    event.target.setAttribute('y', ui.position.top);
  });

});

Here is my HTML code:

<div class="container">
  <div id="wordCloud"></div>
  <div id="wordCloudFinal"></div>
</div>
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
Cunx
  • 1
  • Stack snippet is for **running code** only. I just edited your question to plain code. – Gerardo Furtado Sep 22 '17 at 12:08
  • Thx mate. This is my first time asking question on Stack Overflow lol. – Cunx Sep 22 '17 at 12:10
  • `And also the element cannot be dragged out of its SVG container`, you'll never be able to drag an SVG text element outside an SVG container... – Mark Sep 22 '17 at 14:58
  • As @Mark stated, you can't drag an element of the SVG out of the SVG boundaries. That said, you could create a helper that contains the text from the SVG and is then draggable outside of the SVG. – Twisty Sep 27 '17 at 20:08
  • @Cunx do you have a working example of all your code, in jsfiddle or similar? – Twisty Sep 27 '17 at 20:10
  • Thx mates. I was busy with other stuff past few days thus I didn't check your answers in a timely manner xD. Thank you so much for all your help, but since at this stage it is not likely to drag the elements out of its SVG container, I might just let the user manually type in the words in a text area. Thanks for your idea, @Twisty. But because I will be having several word clouds and each contains 50 words, it would be a super long list if I add all the texts into that list lol. Thank you so much anyways :). – Cunx Sep 28 '17 at 00:52
  • @Cunx 50 words, 100 words, it wouldn't matter. You can make draggable work for whole groups of elements. Been testing things here: https://jsfiddle.net/Twisty/Lap0ye5z/ still not working as I thought it might. – Twisty Sep 28 '17 at 17:51

0 Answers0