Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(452)

Side by Side Diff: ui/file_manager/gallery/js/image_editor/image_view.js

Issue 1608143002: support animated GIF (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nits Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * The overlay displaying the image. 6 * The overlay displaying the image.
7 * 7 *
8 * @param {!HTMLElement} container The container element. 8 * @param {!HTMLElement} container The container element.
9 * @param {!Viewport} viewport The viewport. 9 * @param {!Viewport} viewport The viewport.
10 * @param {!MetadataModel} metadataModel 10 * @param {!MetadataModel} metadataModel
(...skipping 20 matching lines...) Expand all
31 this.imageLoader_ = 31 this.imageLoader_ =
32 new ImageUtil.ImageLoader(this.document_, metadataModel); 32 new ImageUtil.ImageLoader(this.document_, metadataModel);
33 // We have a separate image loader for prefetch which does not get cancelled 33 // We have a separate image loader for prefetch which does not get cancelled
34 // when the selection changes. 34 // when the selection changes.
35 this.prefetchLoader_ = 35 this.prefetchLoader_ =
36 new ImageUtil.ImageLoader(this.document_, metadataModel); 36 new ImageUtil.ImageLoader(this.document_, metadataModel);
37 37
38 this.contentCallbacks_ = []; 38 this.contentCallbacks_ = [];
39 39
40 /** 40 /**
41 * The element displaying the current content. 41 * The content image or canvas element.
42 * @type {HTMLCanvasElement}
43 * @private
44 */
45 this.screenImage_ = null;
46
47 /**
48 * The content canvas element.
49 * @type {(HTMLCanvasElement|HTMLImageElement)} 42 * @type {(HTMLCanvasElement|HTMLImageElement)}
50 * @private 43 * @private
51 */ 44 */
52 this.contentCanvas_ = null; 45 this.contentImage_ = null;
53 46
54 /** 47 /**
55 * True if the image is a preview (not full res). 48 * True if the image is a preview (not full res).
56 * @type {boolean} 49 * @type {boolean}
57 * @private 50 * @private
58 */ 51 */
59 this.preview_ = false; 52 this.preview_ = false;
60 53
61 /** 54 /**
62 * Cached thumbnail image. 55 * Cached thumbnail image.
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 165
173 /** 166 /**
174 * @override 167 * @override
175 */ 168 */
176 ImageView.prototype.getZIndex = function() { return -1; }; 169 ImageView.prototype.getZIndex = function() { return -1; };
177 170
178 /** 171 /**
179 * @override 172 * @override
180 */ 173 */
181 ImageView.prototype.draw = function() { 174 ImageView.prototype.draw = function() {
182 if (!this.contentCanvas_) // Do nothing if the image content is not set. 175 if (!this.contentImage_) // Do nothing if the image content is not set.
183 return; 176 return;
184 this.setTransform_( 177 this.setTransform_(
185 this.contentCanvas_, 178 this.contentImage_,
186 this.viewport_, 179 this.viewport_,
187 new ImageView.Effect.None(), 180 new ImageView.Effect.None(),
188 ImageView.Effect.DEFAULT_DURATION); 181 ImageView.Effect.DEFAULT_DURATION);
189 if ((this.screenImage_ && this.setupDeviceBuffer(this.screenImage_)) ||
190 this.displayedContentGeneration_ !== this.contentGeneration_) {
191 this.displayedContentGeneration_ = this.contentGeneration_;
192 ImageUtil.trace.resetTimer('paint');
193 this.paintDeviceRect(
194 this.contentCanvas_, ImageRect.createFromImage(this.contentCanvas_));
195 ImageUtil.trace.reportTimer('paint');
196 }
197 }; 182 };
198 183
199 /** 184 /**
200 * Applies the viewport change that does not affect the screen cache size (zoom 185 * Applies the viewport change that does not affect the screen cache size (zoom
201 * change or offset change) with animation. 186 * change or offset change) with animation.
202 */ 187 */
203 ImageView.prototype.applyViewportChange = function() { 188 ImageView.prototype.applyViewportChange = function() {
204 var zooming = this.viewport_.getZoom() > 1; 189 if (this.contentImage_) {
205 if (this.contentCanvas_) {
206 // Show full resolution image only for zooming.
207 this.contentCanvas_.style.opacity = zooming ? '1' : '0';
208 this.setTransform_( 190 this.setTransform_(
209 this.contentCanvas_, 191 this.contentImage_,
210 this.viewport_, 192 this.viewport_,
211 new ImageView.Effect.None(), 193 new ImageView.Effect.None(),
212 ImageView.Effect.DEFAULT_DURATION); 194 ImageView.Effect.DEFAULT_DURATION);
213 } 195 }
214 if (this.screenImage_) {
215 this.setTransform_(
216 this.screenImage_,
217 this.viewport_,
218 new ImageView.Effect.None(),
219 ImageView.Effect.DEFAULT_DURATION);
220 }
221 }; 196 };
222 197
223 /** 198 /**
224 * @return {number} The cache generation. 199 * @return {number} The cache generation.
225 */ 200 */
226 ImageView.prototype.getCacheGeneration = function() { 201 ImageView.prototype.getCacheGeneration = function() {
227 return this.contentGeneration_; 202 return this.contentGeneration_;
228 }; 203 };
229 204
230 /** 205 /**
231 * Invalidates the caches to force redrawing the screen canvas. 206 * Invalidates the caches to force redrawing the screen canvas.
232 */ 207 */
233 ImageView.prototype.invalidateCaches = function() { 208 ImageView.prototype.invalidateCaches = function() {
234 this.contentGeneration_++; 209 this.contentGeneration_++;
235 }; 210 };
236 211
237 /** 212 /**
238 * @return {HTMLCanvasElement} The content canvas element. 213 * @return {!HTMLCanvasElement|!HTMLImageElement} The content image(or canvas).
239 */ 214 */
240 ImageView.prototype.getCanvas = function() { return this.contentCanvas_; }; 215 ImageView.prototype.getImage = function() { return assert(this.contentImage_); } ;
241 216
242 /** 217 /**
243 * @return {boolean} True if the a valid image is currently loaded. 218 * @return {boolean} True if the a valid image is currently loaded.
244 */ 219 */
245 ImageView.prototype.hasValidImage = function() { 220 ImageView.prototype.hasValidImage = function() {
246 return !!(!this.preview_ && this.contentCanvas_ && this.contentCanvas_.width); 221 return !!(!this.preview_ && this.contentImage_ && this.contentImage_.width);
247 }; 222 };
248 223
249 /** 224 /**
250 * @return {!HTMLCanvasElement} The cached thumbnail image. 225 * @return {!HTMLCanvasElement} The cached thumbnail image.
251 */ 226 */
252 ImageView.prototype.getThumbnail = function() { 227 ImageView.prototype.getThumbnail = function() {
253 assert(this.thumbnailCanvas_); 228 assert(this.thumbnailCanvas_);
254 return this.thumbnailCanvas_; 229 return this.thumbnailCanvas_;
255 }; 230 };
256 231
(...skipping 17 matching lines...) Expand all
274 // canvas. 249 // canvas.
275 var deviceBounds = this.viewport_.getDeviceBounds(); 250 var deviceBounds = this.viewport_.getDeviceBounds();
276 var scaleX = deviceBounds.width / canvas.width; 251 var scaleX = deviceBounds.width / canvas.width;
277 var scaleY = deviceBounds.height / canvas.height; 252 var scaleY = deviceBounds.height / canvas.height;
278 var deviceRect = new ImageRect( 253 var deviceRect = new ImageRect(
279 imageRect.left * scaleX, 254 imageRect.left * scaleX,
280 imageRect.top * scaleY, 255 imageRect.top * scaleY,
281 imageRect.width * scaleX, 256 imageRect.width * scaleX,
282 imageRect.height * scaleY); 257 imageRect.height * scaleY);
283 258
284 ImageRect.drawImage( 259 if (this.contentImage_.tagName === 'canvas') {
285 this.screenImage_.getContext('2d'), canvas, deviceRect, imageRect); 260 ImageRect.drawImage(
261 this.contentImage_.getContext('2d'), canvas, deviceRect, imageRect);
262 } else {
263 ImageRect.drawImage(this.contentImage_, canvas, deviceRect, imageRect);
yawano 2016/01/21 05:14:38 Is it okay to pass an image element as the first a
ryoh 2016/01/21 07:28:53 Done.
264 }
286 }; 265 };
287 266
288 /** 267 /**
289 * Creates an overlay canvas with properties similar to the screen canvas. 268 * Creates an overlay canvas with properties similar to the screen canvas.
290 * Useful for showing quick feedback when editing. 269 * Useful for showing quick feedback when editing.
291 * 270 *
292 * @return {!HTMLCanvasElement} Overlay canvas. 271 * @return {!HTMLCanvasElement} Overlay canvas.
293 */ 272 */
294 ImageView.prototype.createOverlayCanvas = function() { 273 ImageView.prototype.createOverlayCanvas = function() {
295 var canvas = assertInstanceof(this.document_.createElement('canvas'), 274 var canvas = assertInstanceof(this.document_.createElement('canvas'),
(...skipping 19 matching lines...) Expand all
315 } 294 }
316 if (canvas.height !== deviceRect.height) { 295 if (canvas.height !== deviceRect.height) {
317 canvas.height = deviceRect.height; 296 canvas.height = deviceRect.height;
318 needRepaint = true; 297 needRepaint = true;
319 } 298 }
320 this.setTransform_(canvas, this.viewport_); 299 this.setTransform_(canvas, this.viewport_);
321 return needRepaint; 300 return needRepaint;
322 }; 301 };
323 302
324 /** 303 /**
325 * Gets screen image data with specified size. 304 * Gets screen image canvas with specified size.
326 * @param {number} width 305 * @param {number} width
327 * @param {number} height 306 * @param {number} height
328 * @return {!ImageData} A new ImageData object. 307 * @return {!HTMLCanvasElement} A scaled canvas.
329 */ 308 */
330 ImageView.prototype.getScreenImageDataWith = function(width, height) { 309 ImageView.prototype.getImageCanvasWith = function(width, height) {
331 // If specified size is same with current screen image size, just return it.
332 if (width === this.screenImage_.width &&
333 height === this.screenImage_.height) {
334 return this.screenImage_.getContext('2d').getImageData(
335 0, 0, this.screenImage_.width, this.screenImage_.height);
336 }
337
338 // Resize if these sizes are different. 310 // Resize if these sizes are different.
339 var resizeCanvas = document.createElement('canvas'); 311 var resizeCanvas = assertInstanceof(document.createElement('canvas'),
312 HTMLCanvasElement);
340 resizeCanvas.width = width; 313 resizeCanvas.width = width;
341 resizeCanvas.height = height; 314 resizeCanvas.height = height;
342 315
343 var context = resizeCanvas.getContext('2d'); 316 var context = resizeCanvas.getContext('2d');
344 context.drawImage(this.screenImage_, 317 context.drawImage(this.contentImage_,
345 0, 0, this.screenImage_.width, this.screenImage_.height, 318 0, 0, this.contentImage_.width, this.contentImage_.height,
346 0, 0, resizeCanvas.width, resizeCanvas.height); 319 0, 0, resizeCanvas.width, resizeCanvas.height);
347 return context.getImageData(0, 0, resizeCanvas.width, resizeCanvas.height); 320 return resizeCanvas;
348 }; 321 };
349 322
350 /** 323 /**
351 * @return {boolean} True if the image is currently being loaded. 324 * @return {boolean} True if the image is currently being loaded.
352 */ 325 */
353 ImageView.prototype.isLoading = function() { 326 ImageView.prototype.isLoading = function() {
354 return this.imageLoader_.isBusy(); 327 return this.imageLoader_.isBusy();
355 }; 328 };
356 329
357 /** 330 /**
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 507
535 /** 508 /**
536 * Unloads content. 509 * Unloads content.
537 * @param {ImageRect=} opt_zoomToRect Target rectangle for zoom-out-effect. 510 * @param {ImageRect=} opt_zoomToRect Target rectangle for zoom-out-effect.
538 */ 511 */
539 ImageView.prototype.unload = function(opt_zoomToRect) { 512 ImageView.prototype.unload = function(opt_zoomToRect) {
540 if (this.unloadTimer_) { 513 if (this.unloadTimer_) {
541 clearTimeout(this.unloadTimer_); 514 clearTimeout(this.unloadTimer_);
542 this.unloadTimer_ = null; 515 this.unloadTimer_ = null;
543 } 516 }
544 if (opt_zoomToRect && this.screenImage_) { 517 if (opt_zoomToRect && this.contentImage_) {
545 var effect = this.createZoomEffect(opt_zoomToRect); 518 var effect = this.createZoomEffect(opt_zoomToRect);
546 this.setTransform_(this.screenImage_, this.viewport_, effect); 519 this.setTransform_(this.contentImage_, this.viewport_, effect);
547 this.screenImage_.setAttribute('fade', true); 520 this.contentImage_.setAttribute('fade', true);
548 this.unloadTimer_ = setTimeout(function() { 521 this.unloadTimer_ = setTimeout(function() {
549 this.unloadTimer_ = null; 522 this.unloadTimer_ = null;
550 this.unload(null /* force unload */); 523 this.unload(null /* force unload */);
551 }.bind(this), effect.getSafeInterval()); 524 }.bind(this), effect.getSafeInterval());
552 return; 525 return;
553 } 526 }
554 this.container_.textContent = ''; 527 this.container_.textContent = '';
555 this.contentCanvas_ = null; 528 this.contentImage_ = null;
556 this.screenImage_ = null;
557 }; 529 };
558 530
559 /** 531 /**
560 * @param {!(HTMLCanvasElement|HTMLImageElement)} content The image element. 532 * @param {!(HTMLCanvasElement|HTMLImageElement)} content The image element.
561 * @param {number=} opt_width Image width. 533 * @param {number=} opt_width Image width.
562 * @param {number=} opt_height Image height. 534 * @param {number=} opt_height Image height.
563 * @param {boolean=} opt_preview True if the image is a preview (not full res). 535 * @param {boolean=} opt_preview True if the image is a preview (not full res).
564 * @private 536 * @private
565 */ 537 */
566 ImageView.prototype.replaceContent_ = function( 538 ImageView.prototype.replaceContent_ = function(
567 content, opt_width, opt_height, opt_preview) { 539 content, opt_width, opt_height, opt_preview) {
568 540
569 if (this.contentCanvas_ && this.contentCanvas_.parentNode === this.container_) 541 if (this.contentImage_ && this.contentImage_.parentNode === this.container_)
570 this.container_.removeChild(this.contentCanvas_); 542 this.container_.removeChild(this.contentImage_);
571 543
572 this.screenImage_ = assertInstanceof(this.document_.createElement('canvas'), 544 this.contentImage_ = content;
573 HTMLCanvasElement); 545 this.container_.appendChild(content);
574 this.screenImage_.className = 'image';
575
576 this.contentCanvas_ = content;
577 this.invalidateCaches(); 546 this.invalidateCaches();
578 this.viewport_.setImageSize( 547 this.viewport_.setImageSize(
579 opt_width || this.contentCanvas_.width, 548 opt_width || this.contentImage_.width,
580 opt_height || this.contentCanvas_.height); 549 opt_height || this.contentImage_.height);
581 this.draw(); 550 this.draw();
582 551
583 this.container_.appendChild(this.screenImage_);
584
585 this.preview_ = opt_preview || false; 552 this.preview_ = opt_preview || false;
586 // If this is not a thumbnail, cache the content and the screen-scale image. 553 // If this is not a thumbnail, cache the content and the screen-scale image.
587 if (this.hasValidImage()) { 554 if (this.hasValidImage()) {
588 // Insert the full resolution canvas into DOM so that it can be printed. 555 // Insert the full resolution canvas into DOM so that it can be printed.
589 this.container_.appendChild(this.contentCanvas_); 556 this.container_.appendChild(this.contentImage_);
yawano 2016/01/21 05:14:38 nit: unnecessary. contentImage_ should be children
ryoh 2016/01/21 07:28:53 Done.
590 this.contentCanvas_.classList.add('fullres'); 557 this.contentImage_.classList.add('image');
591 this.setTransform_( 558 this.setTransform_(this.contentImage_, this.viewport_, null, 0);
592 this.contentCanvas_, this.viewport_, null, 0);
593 559
594 this.contentItem_.contentImage = this.contentCanvas_; 560 this.contentItem_.contentImage = this.contentImage_;
595 this.contentItem_.screenImage = this.screenImage_;
596 561
597 // TODO(kaznacheev): It is better to pass screenImage_ as it is usually 562 this.updateThumbnail_(this.contentImage_);
598 // much smaller than contentCanvas_ and still contains the entire image.
599 // Once we implement zoom/pan we should pass contentCanvas_ instead.
600 this.updateThumbnail_(this.screenImage_);
601 563
602 this.contentRevision_++; 564 this.contentRevision_++;
603 for (var i = 0; i !== this.contentCallbacks_.length; i++) { 565 for (var i = 0; i !== this.contentCallbacks_.length; i++) {
604 try { 566 try {
605 this.contentCallbacks_[i](); 567 this.contentCallbacks_[i]();
606 } catch (e) { 568 } catch (e) {
607 console.error(e); 569 console.error(e);
608 } 570 }
609 } 571 }
610 } 572 }
611 }; 573 };
612 574
613 /** 575 /**
614 * Adds a listener for content changes. 576 * Adds a listener for content changes.
615 * @param {function()} callback Callback. 577 * @param {function()} callback Callback.
616 */ 578 */
617 ImageView.prototype.addContentCallback = function(callback) { 579 ImageView.prototype.addContentCallback = function(callback) {
618 this.contentCallbacks_.push(callback); 580 this.contentCallbacks_.push(callback);
619 }; 581 };
620 582
621 /** 583 /**
622 * Updates the cached thumbnail image. 584 * Updates the cached thumbnail image.
623 * 585 *
624 * @param {!HTMLCanvasElement} canvas The source canvas. 586 * @param {!HTMLCanvasElement|!HTMLImageElement} image The source image or
587 * canvas.
625 * @private 588 * @private
626 */ 589 */
627 ImageView.prototype.updateThumbnail_ = function(canvas) { 590 ImageView.prototype.updateThumbnail_ = function(image) {
628 ImageUtil.trace.resetTimer('thumb'); 591 ImageUtil.trace.resetTimer('thumb');
629 var pixelCount = 10000; 592 var pixelCount = 10000;
630 var downScale = 593 var downScale =
631 Math.max(1, Math.sqrt(canvas.width * canvas.height / pixelCount)); 594 Math.max(1, Math.sqrt(image.width * image.height / pixelCount));
632 595
633 this.thumbnailCanvas_ = canvas.ownerDocument.createElement('canvas'); 596 this.thumbnailCanvas_ = image.ownerDocument.createElement('canvas');
634 this.thumbnailCanvas_.width = Math.round(canvas.width / downScale); 597 this.thumbnailCanvas_.width = Math.round(image.width / downScale);
635 this.thumbnailCanvas_.height = Math.round(canvas.height / downScale); 598 this.thumbnailCanvas_.height = Math.round(image.height / downScale);
636 ImageRect.drawImage(this.thumbnailCanvas_.getContext('2d'), canvas); 599 ImageRect.drawImage(this.thumbnailCanvas_.getContext('2d'), image);
637 ImageUtil.trace.reportTimer('thumb'); 600 ImageUtil.trace.reportTimer('thumb');
638 }; 601 };
639 602
640 /** 603 /**
641 * Replaces the displayed image, possibly with slide-in animation. 604 * Replaces the displayed image, possibly with slide-in animation.
642 * 605 *
643 * @param {!(HTMLCanvasElement|HTMLImageElement)} content The image element. 606 * @param {!(HTMLCanvasElement|HTMLImageElement)} newContentImage
607 * The image element.
644 * @param {ImageView.Effect=} opt_effect Transition effect object. 608 * @param {ImageView.Effect=} opt_effect Transition effect object.
645 * @param {number=} opt_width Image width. 609 * @param {number=} opt_width Image width.
646 * @param {number=} opt_height Image height. 610 * @param {number=} opt_height Image height.
647 * @param {boolean=} opt_preview True if the image is a preview (not full res). 611 * @param {boolean=} opt_preview True if the image is a preview (not full res).
648 */ 612 */
649 ImageView.prototype.replace = function( 613 ImageView.prototype.replace = function(
650 content, opt_effect, opt_width, opt_height, opt_preview) { 614 newContentImage, opt_effect, opt_width, opt_height, opt_preview) {
651 var oldScreenImage = this.screenImage_; 615 var oldContentImage = this.contentImage_;
652 var oldViewport = this.viewport_.clone(); 616 var oldViewport = this.viewport_.clone();
653 this.replaceContent_(content, opt_width, opt_height, opt_preview); 617 this.replaceContent_(newContentImage, opt_width, opt_height, opt_preview);
654 if (!opt_effect) { 618 if (!opt_effect) {
655 if (oldScreenImage)
656 oldScreenImage.parentNode.removeChild(oldScreenImage);
657 return; 619 return;
658 } 620 }
659 621
660 assert(this.screenImage_); 622 assert(this.contentImage_);
661 var newScreenImage = this.screenImage_;
662 this.viewport_.resetView(); 623 this.viewport_.resetView();
663 624
664 if (oldScreenImage) 625 if (oldContentImage)
665 ImageUtil.setAttribute(newScreenImage, 'fade', true); 626 ImageUtil.setAttribute(newContentImage, 'fade', true);
666 this.setTransform_( 627 this.setTransform_(
667 newScreenImage, this.viewport_, opt_effect, 0 /* instant */); 628 newContentImage, this.viewport_, opt_effect, 0 /* instant */);
668 this.setTransform_(
669 content, this.viewport_, opt_effect, 0 /* instant */);
670 629
671 // We need to call requestAnimationFrame twice here. The first call is for 630 // We need to call requestAnimationFrame twice here. The first call is for
672 // commiting the styles of beggining of transition that are assigned above. 631 // commiting the styles of beggining of transition that are assigned above.
673 // The second call is for assigning and commiting the styles of end of 632 // The second call is for assigning and commiting the styles of end of
674 // transition, which triggers transition animation. 633 // transition, which triggers transition animation.
675 requestAnimationFrame(function() { 634 requestAnimationFrame(function() {
676 requestAnimationFrame(function() { 635 requestAnimationFrame(function() {
677 this.setTransform_( 636 this.setTransform_(
678 newScreenImage, 637 newContentImage,
679 this.viewport_, 638 this.viewport_,
680 null, 639 null,
681 opt_effect ? opt_effect.getDuration() : undefined); 640 opt_effect ? opt_effect.getDuration() : undefined);
682 this.setTransform_( 641 if (oldContentImage) {
683 content, 642 ImageUtil.setAttribute(newContentImage, 'fade', false);
684 this.viewport_, 643 ImageUtil.setAttribute(oldContentImage, 'fade', true);
685 null,
686 opt_effect ? opt_effect.getDuration() : undefined);
687 if (oldScreenImage) {
688 ImageUtil.setAttribute(newScreenImage, 'fade', false);
689 ImageUtil.setAttribute(oldScreenImage, 'fade', true);
690 var reverse = opt_effect.getReverse(); 644 var reverse = opt_effect.getReverse();
691 if (reverse) { 645 if (reverse) {
692 this.setTransform_(oldScreenImage, oldViewport, reverse); 646 this.setTransform_(oldContentImage, oldViewport, reverse);
693 setTimeout(function() { 647 setTimeout(function() {
694 if (oldScreenImage.parentNode) 648 if (oldContentImage.parentNode)
695 oldScreenImage.parentNode.removeChild(oldScreenImage); 649 oldContentImage.parentNode.removeChild(oldContentImage);
696 }, reverse.getSafeInterval()); 650 }, reverse.getSafeInterval());
697 } else { 651 } else {
698 if (oldScreenImage.parentNode) 652 if (oldContentImage.parentNode)
699 oldScreenImage.parentNode.removeChild(oldScreenImage); 653 oldContentImage.parentNode.removeChild(oldContentImage);
700 } 654 }
701 } 655 }
702 }.bind(this)); 656 }.bind(this));
703 }.bind(this)); 657 }.bind(this));
704 }; 658 };
705 659
706 /** 660 /**
707 * @param {!HTMLCanvasElement|!HTMLImageElement} element The element to 661 * @param {!HTMLCanvasElement|!HTMLImageElement} element The element to
708 * transform. 662 * transform.
709 * @param {!Viewport} viewport Viewport to be used for calculating 663 * @param {!Viewport} viewport Viewport to be used for calculating
(...skipping 29 matching lines...) Expand all
739 * the new image to visualize the operation. 693 * the new image to visualize the operation.
740 * 694 *
741 * @param {!HTMLCanvasElement} canvas New content canvas. 695 * @param {!HTMLCanvasElement} canvas New content canvas.
742 * @param {ImageRect} imageCropRect The crop rectangle in image coordinates. 696 * @param {ImageRect} imageCropRect The crop rectangle in image coordinates.
743 * Null for rotation operations. 697 * Null for rotation operations.
744 * @param {number} rotate90 Rotation angle in 90 degree increments. 698 * @param {number} rotate90 Rotation angle in 90 degree increments.
745 * @return {number} Animation duration. 699 * @return {number} Animation duration.
746 */ 700 */
747 ImageView.prototype.replaceAndAnimate = function( 701 ImageView.prototype.replaceAndAnimate = function(
748 canvas, imageCropRect, rotate90) { 702 canvas, imageCropRect, rotate90) {
749 assert(this.screenImage_); 703 assert(this.contentImage_);
750 704
751 var oldImageBounds = { 705 var oldImageBounds = {
752 width: this.viewport_.getImageBounds().width, 706 width: this.viewport_.getImageBounds().width,
753 height: this.viewport_.getImageBounds().height 707 height: this.viewport_.getImageBounds().height
754 }; 708 };
755 var oldScreenImage = this.screenImage_; 709 var oldScreenImage = this.contentImage_;
756 this.replaceContent_(canvas); 710 this.replaceContent_(canvas);
757 var newScreenImage = this.screenImage_; 711 var newScreenImage = this.contentImage_;
758 var effect = rotate90 ? 712 var effect = rotate90 ?
759 new ImageView.Effect.Rotate(rotate90 > 0) : 713 new ImageView.Effect.Rotate(rotate90 > 0) :
760 new ImageView.Effect.Zoom( 714 new ImageView.Effect.Zoom(
761 oldImageBounds.width, oldImageBounds.height, assert(imageCropRect)); 715 oldImageBounds.width, oldImageBounds.height, assert(imageCropRect));
762 716
763 this.setTransform_(newScreenImage, this.viewport_, effect, 0 /* instant */); 717 this.setTransform_(newScreenImage, this.viewport_, effect, 0 /* instant */);
764 718
765 oldScreenImage.parentNode.appendChild(newScreenImage);
766 oldScreenImage.parentNode.removeChild(oldScreenImage);
767
768 // Let the layout fire, then animate back to non-transformed state. 719 // Let the layout fire, then animate back to non-transformed state.
769 setTimeout( 720 setTimeout(
770 this.setTransform_.bind( 721 this.setTransform_.bind(
771 this, newScreenImage, this.viewport_, null, effect.getDuration()), 722 this, newScreenImage, this.viewport_, null, effect.getDuration()),
772 0); 723 0);
773 724
774 return effect.getSafeInterval(); 725 return effect.getSafeInterval();
775 }; 726 };
776 727
777 /** 728 /**
778 * Visualizes "undo crop". Shrink the current image to the given crop rectangle 729 * Visualizes "undo crop". Shrink the current image to the given crop rectangle
779 * while fading in the new image. 730 * while fading in the new image.
780 * 731 *
781 * @param {!HTMLCanvasElement} canvas New content canvas. 732 * @param {!HTMLCanvasElement} canvas New content canvas.
782 * @param {!ImageRect} imageCropRect The crop rectangle in image coordinates. 733 * @param {!ImageRect} imageCropRect The crop rectangle in image coordinates.
783 * @return {number} Animation duration. 734 * @return {number} Animation duration.
784 */ 735 */
785 ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) { 736 ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) {
786 var oldScreenImage = this.screenImage_; 737 var oldScreenImage = assert(this.contentImage_);
738 oldScreenImage.style.zIndex = 1000;
787 this.replaceContent_(canvas); 739 this.replaceContent_(canvas);
788 var newScreenImage = this.screenImage_; 740 this.container_.appendChild(oldScreenImage);
741 var newScreenImage = this.contentImage_;
789 var setFade = ImageUtil.setAttribute.bind(null, assert(newScreenImage), 742 var setFade = ImageUtil.setAttribute.bind(null, assert(newScreenImage),
790 'fade'); 743 'fade');
791 setFade(true); 744 setFade(true);
792 oldScreenImage.parentNode.insertBefore(newScreenImage, oldScreenImage);
793 var effect = new ImageView.Effect.Zoom( 745 var effect = new ImageView.Effect.Zoom(
794 this.viewport_.getImageBounds().width, 746 this.viewport_.getImageBounds().width,
795 this.viewport_.getImageBounds().height, 747 this.viewport_.getImageBounds().height,
796 imageCropRect); 748 imageCropRect);
749 // Animate to the transformed state.
750 setTimeout(function() {
751 this.setTransform_(oldScreenImage, this.viewport_, effect);
752 }.bind(this));
yawano 2016/01/21 05:14:38 nit: add 0 as second argument. We don't emit it.
ryoh 2016/01/21 07:28:53 Done.
797 753
798 // Animate to the transformed state.
799 this.setTransform_(oldScreenImage, this.viewport_, effect);
800 setTimeout(setFade.bind(null, false), 0); 754 setTimeout(setFade.bind(null, false), 0);
755
801 setTimeout(function() { 756 setTimeout(function() {
802 if (oldScreenImage.parentNode) 757 if (oldScreenImage.parentNode)
803 oldScreenImage.parentNode.removeChild(oldScreenImage); 758 oldScreenImage.parentNode.removeChild(oldScreenImage);
804 }, effect.getSafeInterval()); 759 }, effect.getSafeInterval());
805 760
806 return effect.getSafeInterval(); 761 return effect.getSafeInterval();
807 }; 762 };
808 763
809 /* Transition effects */ 764 /* Transition effects */
810 765
811 /** 766 /**
812 * Base class for effects. 767 * Base class for effects.
813 * 768 *
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 970
1016 ImageView.Effect.Rotate.prototype = { __proto__: ImageView.Effect.prototype }; 971 ImageView.Effect.Rotate.prototype = { __proto__: ImageView.Effect.prototype };
1017 972
1018 /** 973 /**
1019 * @override 974 * @override
1020 */ 975 */
1021 ImageView.Effect.Rotate.prototype.transform = function(element, viewport) { 976 ImageView.Effect.Rotate.prototype.transform = function(element, viewport) {
1022 return viewport.getRotatingTransformation( 977 return viewport.getRotatingTransformation(
1023 element.width, element.height, this.orientation_ ? -1 : 1); 978 element.width, element.height, this.orientation_ ? -1 : 1);
1024 }; 979 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698