timdream / wordcloud2.js

Tag cloud/Wordle presentation on 2D canvas or HTML
https://wordcloud2-js.timdream.org/
MIT License
2.38k stars 514 forks source link

Problems applying a mask #94

Closed RidleyDeckard closed 7 years ago

RidleyDeckard commented 7 years ago

Hi there, I'm having real problems applying a mask, I can get it to work using your example without any problems, but when I try to set it up in a new page it seems to load the mask in, but then just ignores it.

I've set it up so that like in your demo it draws the word cloud, you then add the image mask and hit run, but it is just like the mask isn't there. Any idea where I'm going wrong?

 var $canvas = $('#canvas');
 var $mask = $('#config-mask');
var maskused = false;
var wordsdrawn = 0;
 var maskCanvas;

 var words = "British athletes who may lose  world records  received an apology from the man responsible for the controversial anti-doping proposal. Paula Radcliffe, Jonathan Edwards and Colin Jackson are among collateral damage says European Athletics taskforce chair Pierce O'Callaghan. But he told BBC Radio 5 live: There is a bigger picture out there. All pre-2005 records could be rewritten under the new rules, which need to be ratified by governing body, the IAAF. O'Callaghan said: Apologies to the athletes, we never intended to damage  reputation and legacy. It is intended to give the public belief and credibility in what  are watching in the sport. It's going to affect everybody - and it lumps us all in  the cheats Read more analysis from Steve Cram, former world 1500m champion, below But BBC athletics commentator and former world 1500m champion Steve Cram called the proposals an easy route out and a PR exercise. Cram set world records for the 1500m, mile and 2,000m in the space of 19 days in 1985, and still holds the European records for the latter two distances - although under the proposals those pre-2005 European records would join world records in being reset. He added that the measures are not going to stop people cheating. The IAAF (International Association of Athletics Federations) has only stored blood and urine samples since 2005 and current records that do not meet the new criteria would remain on an all-time list, but not be officially recognised as records if the IAAF accepts the proposal. European Athletics president Hansen said he would encourage the IAAF to adopt the proposal at its August council meeting, while IAAF president Lord Coe said the changes were a step in the right direction. The world records to fall would include Edwards' triple jump mark of 18.29m - set in 1995 - and Jackson's 1994 indoor 60m hurdles world best of 7.30secs, as well as Radcliffe's marathon time of two hours 15 minutes 25 seconds, set in 2003 using two male pacemakers. O'Callaghan compared the changes to English football introducing the Premier League above the First Division in 1992 and rugby union's Five Nations becoming the Six Nations in 2000, and said the records will be recalibrated. Paula Radcliffe One of the records under threat is Radcliffe's marathon mark of two hours 15 minutes 25 seconds, set in 2003 using two male pacemakers We hope people look at it in that vein, rather than stripping great athletes like Paula of  records, added O'Callaghan, who said he had spoken to Radcliffe and Edwards. Unfortunately Paula ran her records in a golden period that happens to be two years before the technology moved on. People should not look at Paula's records and throw them in  doping records - she achieved her performance, as did Jonathan,  100% integrity. This is about the bigger picture of reform in athletics and ensuring the public in events like the London World Championships [in August 2017], that they can believe what they are watching. What are the taskforce's proposals? If the proposals are accepted by the IAAF, a world or European record would only be recognised if it meets all three of the following criteria: It was achieved at a competition on a list of approved international events where the highest standards of officiating and technical equipment can be guaranteed; The athlete had been subject to an agreed number of doping control tests in the months leading up to it; The doping control sample taken after the record was stored and available for re-testing for 10 years. More than 100 Olympic athletes who competed at the 2008 and 2012 Games have been sanctioned for doping after the International Olympic Committee embarked on a programme of retesting old samples. But Radcliffe has called the proposals cowardly and accused the governing bodies of failing clean athletes. Jackson added: They are making excuses on why they are doing it. I think it is a wrong reason why they are doing it. We all understand the situation  doping but it is not the fault of the clean athletes. Read more: Jackson describes European Athletics plans as 'ridiculous' Analysis - 'It lumps us in  the cheats' Steve Cram, former world 1500m champion, now BBC athletics commentator We are all trying to make sure we look at ways we can improve the integrity of our sport but this smacks to me as an easy route out. There are massive issues for the sport to contend  and this, for me, is almost a PR exercise. I can't believe that if the public don't have credibility now that they are going to have it going forward. I don't think it changes much. It's very confusing for people, and it's going to affect everybody all the way down. It lumps us all in  those cheats. It's not our fault that over the years the sport did not police itself properly. It's not our fault they didn't do  job. I don't think it's going to change anything. It's not going to stop people cheating. I was chatting  the president of European Athletics and asked have you thought this through?. I am not convinced they have. All the member federations of European Athletics will have to scrap  national records because you can't have a national record quicker than the European record, and so on. Part of the worst aspect of it is that in the document that they are putting forward, they are talking about preserving the dignity of the athletes as well. It's about preserving  own dignity. It's an easy cop out. They haven't been able to make the tough decisions. If there are records that they believe that shouldn't be on the books then they should go after those  whatever scrutiny they have can. If they can't do that, then this is  problem to deal  We all lose our records eventually. It's fine somebody comes along and breaks it but what is not fair is that the federation decides that is not the record any more. As a broadcaster, what do I say to the public? In the early days, there was no drug testing, did we scrap all of those records? No. Then, drug testing was introduced and now we have tougher drug testing. That's fine, we all accept that. Maybe some things slipped through the net in the past but you can't keep drawing a line every five years. The farcical thing they are going to end up , is that there will still be people holding records who have had a ban - but the records they set were before the ban and those will still stand. Somebody fails a test in 2015 and then all of  performances for that period are scrapped. But if they set a record in 2012, that stays. That's silly.".replace(/[^a-zA-Z ]/g, "");

  var arr = words.split(' ');
    console.log(arr);
    var obj = {};
    var i = 0;
    for (i = 0; i < arr.length; i++) {
        if ((arr[i].length>3)&&(arr[i]!='that')&&(arr[i]!='they')&&(arr[i]!='have')&&(arr[i]!='this')&&(arr[i]!='cant')&&(arr[i]!='then')&&(arr[i]!='will')&&(arr[i]!='said')) {
        if (arr[i] != '') {
            if (!obj[arr[i]]) {
                obj[arr[i]] = 0;
            }
            obj[arr[i]]++;
        }
        }
    }

    var list = [];
    for (var key in obj) {
        item = [];
        item[0]=key;
        item[1]=obj[key];
        list.push(item);
    }
 $mask.on('change', function() {
 maskCanvas = null;

var file = $mask[0].files[0];

if (!file) {
  return;
}
maskCanvas = null;
var url = window.URL.createObjectURL(file);
var img = new Image();
img.src = url;

    img.onload = function readPixels() {
  window.URL.revokeObjectURL(url);
  maskCanvas = document.createElement('canvas');
  maskCanvas.width = img.width;
  maskCanvas.height = img.height;

  var ctx = maskCanvas.getContext('2d');
  ctx.drawImage(img, 0, 0, img.width, img.height);

  var imageData = ctx.getImageData(
    0, 0, maskCanvas.width, maskCanvas.height);
  var newImageData = ctx.createImageData(imageData);
  for (var i = 0; i < imageData.data.length; i += 4) {
    var tone = imageData.data[i] +
      imageData.data[i + 1] +
      imageData.data[i + 2];
    var alpha = imageData.data[i + 3];
    if (alpha < 128 || tone > 128 * 3) {
      // Area not to draw
      newImageData.data[i] =
        newImageData.data[i + 1] =
        newImageData.data[i + 2] = 255;
      newImageData.data[i + 3] = 0;
    } else {
      // Area to draw
      newImageData.data[i] =
        newImageData.data[i + 1] =
        newImageData.data[i + 2] = 0;
      newImageData.data[i + 3] = 255;
    }
  }
  ctx.putImageData(newImageData, 0, 0);
        maskused = true;
    }
});

 var run = function run() {

// Set the width and height
var width = 1280;
var height = 720;
var pixelWidth = width;
var pixelHeight = height;
 console.log("height"+height);

  $canvas.css({'width': '', 'height': '' });

$canvas.attr('width', pixelWidth);
$canvas.attr('height', pixelHeight);

if (maskCanvas) {

  /* Determine bgPixel by creating
     another canvas and fill the specified background color. */
  var bctx = document.createElement('canvas').getContext('2d');

  bctx.fillStyle = '#fff';
  bctx.fillRect(0, 0, 1, 1);
  var bgPixel = bctx.getImageData(0, 0, 1, 1).data;

  var maskCanvasScaled =
    document.createElement('canvas');
  maskCanvasScaled.width = $canvas[0].width;
  maskCanvasScaled.height = $canvas[0].height;
  var ctx = maskCanvasScaled.getContext('2d');
    console.log($canvas[0]);
    console.log(maskCanvasScaled.height);
  ctx.drawImage(maskCanvas,
    0, 0, maskCanvas.width, maskCanvas.height,
    0, 0, maskCanvasScaled.width, maskCanvasScaled.height);

  var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  var newImageData = ctx.createImageData(imageData);
  for (var i = 0; i < imageData.data.length; i += 4) {
    if (imageData.data[i + 3] > 128) {
      newImageData.data[i] = bgPixel[0];
      newImageData.data[i + 1] = bgPixel[1];
      newImageData.data[i + 2] = bgPixel[2];
      newImageData.data[i + 3] = bgPixel[3];
    } else {
      // This color must not be the same w/ the bgPixel.
      newImageData.data[i] = bgPixel[0];
      newImageData.data[i + 1] = bgPixel[1];
      newImageData.data[i + 2] = bgPixel[2];
      newImageData.data[i + 3] = bgPixel[3] ? (bgPixel[3] - 1) : 0;
    }
  }

  ctx.putImageData(newImageData, 0, 0);

  ctx = $canvas[0].getContext('2d');
  ctx.drawImage(maskCanvasScaled, 0, 0);

  maskCanvasScaled = ctx = imageData = newImageData = bctx = bgPixel = undefined;
}

 WordCloud($canvas[0], { 
        list: list,
        gridSize: 4,
        weightFactor: 16,
        fontFamily: 'Impact, serif',
   clearCanvas: true,
        color: '#000',
        backgroundColor: '#fff',
        rotateRatio: .5,
    shuffle: false,
        rotationSteps: 1,
        ellipticity: 1});
  };

run();
 </script>
 </html>
RidleyDeckard commented 7 years ago

This is the image I'm trying to using as the mask;

elephant

Justinnng commented 7 years ago

I have same problem as you, did you fix it?

ozorOzora commented 7 years ago

Same here.

Justinnng commented 7 years ago

@ozorOzora I've fixed, just make sure you run WordCloud(word_canvas, options); after image.onload. I fixed by

setTimeout(()=>{
                WordCloud(word_canvas, options);
        }, 500)
timdream commented 7 years ago

@Justinnng Thank you for helping out. Closing since it's not related to WordCloud itself.

bindugupta commented 6 years ago

I am not able to understand how to apply a mask . My wordcloud is not a proper circle so I am thinking of applying a mask of an image of circle. Can somebody share how to do this ?

image

So far , I have this by adding shape='circle' in the options but its not a perfect circle

mohammad-hormati commented 2 years ago

i have the same problem , Can anyone tell me how to implement it in React? @timdream timdream