0

I want to create an animated app demo: load the sceenshot1 -> button click -> switch to sceenshot2 -> typing 2 lines of text. I saw a site doing similar animation (https://www.pixelapse.com/).

Is html5 canvas or CSS3 the right tool to create this animation? I found this library. https://github.com/GwennaelBuchet/SceneGraph.js. Are there any other tools to create this kind of animation?

enter image description here

enter image description here

angelokh
  • 9,426
  • 9
  • 69
  • 139
  • So you're looking to have a comments-balloon that appends comments as additional comments come in? – markE Oct 02 '14 at 16:28
  • Yes, the background image should load first -> button click -> switch to next background image -> show 2 lines of text. This is the animation I want to achieve. – angelokh Oct 02 '14 at 16:56
  • You desire is more clear now, thanks! So what code do you have so far? – markE Oct 02 '14 at 17:03
  • I edited the question again. I searched and only found this lib. https://github.com/GwennaelBuchet/SceneGraph.js – angelokh Oct 02 '14 at 17:06

1 Answers1

2

Here's an example and Demo to get you started:

One comment:

enter image description here

Multiple comments:

enter image description here

  • Draw the image associated with the comment: context.drawImage

  • Draw the text part of the comment and wrap it onto multiple lines as required: see the wrapText function in the example below.

  • Draw the rounded rectangle around the images+comments: see the roundedRect function in the example below.

Example code and Demo to get you started:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;

var x = 25;
var y = 25;
var width = 350;
var height = 0;
var radius = 10;
var padding = 10;

var comments = [];
var commentDisplayCount = 1;
comments.push({
  imgIndex: 0,
  name: 'jennifer',
  comment: 'Lacking contrast in the colors around this blue thing on top of the swan origami. What do you think we can do to punch it up a bit?'
});
comments.push({
  imgIndex: 1,
  name: 'Richard',
  comment: 'Maybe we try a darker shade of blue in the sides of that blue thing?'
});
comments.push({
  imgIndex: 0,
  name: 'jennifer',
  comment: 'Blah, Blah, Blah'
});
comments.push({
  imgIndex: 1,
  name: 'Richard',
  comment: 'Yep, Yep, Yep'
});

// preload images
// put the paths to your images in imageURLs[]
var imageURLs = [];
// push all your image urls!
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/face1.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/face2.png");

// the loaded images will be placed in imgs[]
var imgs = [];
var imagesOK = 0;
loadAllImages(start);

function loadAllImages(callback) {
  for (var i = 0; i < imageURLs.length; i++) {
    var img = new Image();
    imgs.push(img);
    img.onload = function() {
      imagesOK++;
      if (imagesOK >= imageURLs.length) {
        callback();
      }
    };
    img.onerror = function() {
      alert("image load failed");
    }
    img.crossOrigin = "anonymous";
    img.src = imageURLs[i];
  }
}

function start() {

  // the imgs[] array now holds fully loaded images
  // the imgs[] are in the same order as imageURLs[]

  draw();
}


function draw() {
  var accumHeight = 0;
  var imageWidth = 35;

  ctx.clearRect(0, 0, cw, ch);
  for (var i = 0; i < commentDisplayCount; i++) {

    ctx.drawImage(imgs[comments[i].imgIndex], x + padding, y + accumHeight + padding, 25, 25);

    accumHeight = wrapText(
      comments[i].comment,
      x + padding + imageWidth,
      y + padding + accumHeight,
      width - padding * 2 - imageWidth, 12, "verdana"
    );

  }
  roundedRect(x, y, width, accumHeight, radius);
}


function roundedRect(x, y, w, h, r) {
  ctx.beginPath();
  ctx.moveTo(x + r, y);
  ctx.lineTo(x + w - r, y);
  ctx.quadraticCurveTo(x + w, y, x + w, y + r);
  ctx.lineTo(x + w, y + h - r);
  ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
  ctx.lineTo(x + r, y + h);
  ctx.quadraticCurveTo(x, y + h, x, y + h - r);
  ctx.lineTo(x, y + r);
  ctx.quadraticCurveTo(x, y, x + r, y);
  ctx.closePath();
  ctx.strokeStyle = 'black';
  ctx.fillStyle = 'white';
  ctx.stroke();
  ctx.globalCompositeOperation = 'destination-over';
  ctx.fill();
  ctx.globalCompositeOperation = 'source-over';
}


function wrapText(text, x, y, maxWidth, fontSize, fontFace) {
  var words = text.split(' ');
  var line = '';
  var lineHeight = fontSize;
  y += fontSize;
  ctx.font = fontSize + " " + fontFace;
  ctx.fillStyle = 'black';
  for (var n = 0; n < words.length; n++) {
    var testLine = line + words[n] + ' ';
    var metrics = ctx.measureText(testLine);
    var testWidth = metrics.width;
    if (testWidth > maxWidth) {
      ctx.fillText(line, x, y);
      line = words[n] + ' ';
      y += lineHeight;
    } else {
      line = testLine;
    }
  }
  ctx.fillText(line, x, y);
  return (y);
}



$("#test").click(function() {
  if (++commentDisplayCount > comments.length) {
    commentDisplayCount = comments.length;
  }
  draw();
});
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id="test">Add a Comment</button>
<br>
<canvas id="canvas" width=400 height=400></canvas>
markE
  • 102,905
  • 11
  • 164
  • 176