Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 * @param {HTMLElement} container The container element. | 7 * @param {HTMLElement} container The container element. |
| 8 * @param {Viewport} viewport The viewport. | 8 * @param {Viewport} viewport The viewport. |
| 9 * @param {MetadataCache} metadataCache The metadataCache. | 9 * @param {MetadataCache} metadataCache The metadataCache. |
| 10 */ | 10 */ |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 40 this.screenImage_ = null; | 40 this.screenImage_ = null; |
| 41 | 41 |
| 42 this.localImageTransformFetcher_ = function(url, callback) { | 42 this.localImageTransformFetcher_ = function(url, callback) { |
| 43 metadataCache.get(url, 'fetchedMedia', function(fetchedMedia) { | 43 metadataCache.get(url, 'fetchedMedia', function(fetchedMedia) { |
| 44 callback(fetchedMedia.imageTransform); | 44 callback(fetchedMedia.imageTransform); |
| 45 }); | 45 }); |
| 46 }; | 46 }; |
| 47 } | 47 } |
| 48 | 48 |
| 49 /** | 49 /** |
| 50 * Duration of image editing transitions. | 50 * Duration for transition between images. |
| 51 */ | 51 */ |
| 52 ImageView.ANIMATION_DURATION = 180; | 52 ImageView.ANIMATION_DURATION = 180; |
| 53 | 53 |
| 54 /** | 54 /** |
| 55 * A timeout for use with setTimeout when one wants to wait until the animation | 55 * A timeout for use with setTimeout when one wants to wait until the animation |
| 56 * is done. Times 2 is added as a safe margin. | 56 * is done. Times 2 is added as a safe margin. |
| 57 */ | 57 */ |
| 58 ImageView.ANIMATION_WAIT_INTERVAL = ImageView.ANIMATION_DURATION * 2; | 58 ImageView.ANIMATION_WAIT_INTERVAL = ImageView.ANIMATION_DURATION * 2; |
| 59 | 59 |
| 60 /** | 60 /** |
| 61 * Duration of transition when loading the first image or unloading the last. | |
| 62 */ | |
| 63 ImageView.ZOOM_ANIMATION_DURATION = 350; | |
| 64 | |
| 65 /** | |
| 61 * If the user flips though images faster than this interval we do not apply | 66 * If the user flips though images faster than this interval we do not apply |
| 62 * the slide-in/slide-out transition. | 67 * the slide-in/slide-out transition. |
| 63 */ | 68 */ |
| 64 ImageView.FAST_SCROLL_INTERVAL = 300; | 69 ImageView.FAST_SCROLL_INTERVAL = 300; |
| 65 | 70 |
| 66 /** | 71 /** |
| 67 * Image load type: full resolution image loaded from cache. | 72 * Image load type: full resolution image loaded from cache. |
| 68 */ | 73 */ |
| 69 ImageView.LOAD_TYPE_CACHED_FULL = 0; | 74 ImageView.LOAD_TYPE_CACHED_FULL = 0; |
| 70 | 75 |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 490 this.screenCache_.renameItem(this.contentID_, newUrl); | 495 this.screenCache_.renameItem(this.contentID_, newUrl); |
| 491 this.contentID_ = newUrl; | 496 this.contentID_ = newUrl; |
| 492 }; | 497 }; |
| 493 | 498 |
| 494 /** | 499 /** |
| 495 * Unload content. | 500 * Unload content. |
| 496 * | 501 * |
| 497 * @param {Rect} zoomToRect Target rectangle for zoom-out-effect. | 502 * @param {Rect} zoomToRect Target rectangle for zoom-out-effect. |
| 498 */ | 503 */ |
| 499 ImageView.prototype.unload = function(zoomToRect) { | 504 ImageView.prototype.unload = function(zoomToRect) { |
| 500 if (zoomToRect) { | 505 if (this.unloadTimer_) { |
| 501 this.setTransform(this.screenImage_, this.createZoomEffect(zoomToRect)); | 506 clearTimeout(this.unloadTimer_); |
| 507 this.unloadTimer_ = null; | |
| 508 } | |
| 509 if (zoomToRect && this.screenImage_) { | |
| 510 var effect = this.createZoomEffect(zoomToRect); | |
| 511 this.setTransform(this.screenImage_, effect, effect.duration); | |
| 512 this.screenImage_.setAttribute('fade', true); | |
| 502 this.unloadTimer_ = setTimeout(function() { | 513 this.unloadTimer_ = setTimeout(function() { |
| 503 this.unloadTimer_ = null; | 514 this.unloadTimer_ = null; |
| 504 this.unload(null /* force unload */); | 515 this.unload(null /* force unload */); |
| 505 }.bind(this), | 516 }.bind(this), |
| 506 ImageView.ANIMATION_WAIT_INTERVAL + 100); | 517 effect.duration + 100 /* error margin */); |
| 507 return; | 518 return; |
| 508 } | 519 } |
| 509 if (this.unloadTimer_) { | |
| 510 clearTimeout(this.unloadTimer_); | |
| 511 this.unloadTimer_ = null; | |
| 512 } | |
| 513 this.container_.textContent = ''; | 520 this.container_.textContent = ''; |
| 514 this.contentCanvas_ = null; | 521 this.contentCanvas_ = null; |
| 515 this.screenImage_ = null; | 522 this.screenImage_ = null; |
| 516 this.videoElement_ = null; | 523 this.videoElement_ = null; |
| 517 }; | 524 }; |
| 518 | 525 |
| 519 /** | 526 /** |
| 520 * | 527 * |
| 521 * @param {HTMLCanvasElement|HTMLVideoElement} content The image element. | 528 * @param {HTMLCanvasElement|HTMLVideoElement} content The image element. |
| 522 * @param {boolean} opt_reuseScreenCanvas True if it is OK to reuse the screen | 529 * @param {boolean} opt_reuseScreenCanvas True if it is OK to reuse the screen |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 626 content, opt_effect, opt_width, opt_height, opt_preview) { | 633 content, opt_effect, opt_width, opt_height, opt_preview) { |
| 627 var oldScreenImage = this.screenImage_; | 634 var oldScreenImage = this.screenImage_; |
| 628 | 635 |
| 629 this.replaceContent_( | 636 this.replaceContent_( |
| 630 content, !opt_effect, opt_width, opt_height, opt_preview); | 637 content, !opt_effect, opt_width, opt_height, opt_preview); |
| 631 | 638 |
| 632 if (!opt_effect) return; | 639 if (!opt_effect) return; |
| 633 | 640 |
| 634 var newScreenImage = this.screenImage_; | 641 var newScreenImage = this.screenImage_; |
| 635 | 642 |
| 636 ImageUtil.setAttribute(newScreenImage, 'fade', true); | 643 if (oldScreenImage) |
| 644 ImageUtil.setAttribute(newScreenImage, 'fade', true); | |
| 637 this.setTransform(newScreenImage, opt_effect); | 645 this.setTransform(newScreenImage, opt_effect); |
| 638 this.container_.appendChild(newScreenImage); | 646 this.container_.appendChild(newScreenImage); |
| 639 | 647 |
| 640 setTimeout(function() { | 648 setTimeout(function() { |
| 641 ImageUtil.setAttribute(newScreenImage, 'fade', false); | 649 this.setTransform(newScreenImage, null, opt_effect && opt_effect.duration); |
| 642 this.setTransform(newScreenImage); | |
| 643 if (oldScreenImage) { | 650 if (oldScreenImage) { |
| 651 ImageUtil.setAttribute(newScreenImage, 'fade', false); | |
| 644 ImageUtil.setAttribute(oldScreenImage, 'fade', true); | 652 ImageUtil.setAttribute(oldScreenImage, 'fade', true); |
| 645 if (opt_effect.getReverse) | 653 if (opt_effect.getReverse) |
| 646 this.setTransform(oldScreenImage, opt_effect.getReverse()); | 654 this.setTransform(oldScreenImage, opt_effect.getReverse()); |
| 647 else | 655 else |
| 648 console.error('Cannot revert an effect.'); | 656 console.error('Cannot revert an effect.'); |
| 649 setTimeout(function() { | 657 setTimeout(function() { |
| 650 oldScreenImage.parentNode.removeChild(oldScreenImage); | 658 oldScreenImage.parentNode.removeChild(oldScreenImage); |
| 651 }, ImageView.ANIMATION_WAIT_INTERVAL); | 659 }, ImageView.ANIMATION_WAIT_INTERVAL); |
| 652 } | 660 } |
| 653 }.bind(this), 0); | 661 }.bind(this), 0); |
| 654 }; | 662 }; |
| 655 | 663 |
| 656 /** | 664 /** |
| 657 * @param {HTMLCanvasElement|HTMLVideoElement} element The element to transform. | 665 * @param {HTMLCanvasElement|HTMLVideoElement} element The element to transform. |
| 658 * @param {ImageView.Effect} opt_effect The effect to apply. | 666 * @param {ImageView.Effect} opt_effect The effect to apply. |
| 667 * @param {number} opt_duration Transition duration. | |
|
dgozman
2012/09/14 15:17:38
number=
| |
| 659 */ | 668 */ |
| 660 ImageView.prototype.setTransform = function(element, opt_effect) { | 669 ImageView.prototype.setTransform = function(element, opt_effect, opt_duration) { |
| 661 if (!opt_effect) opt_effect = new ImageView.Effect.None(); | 670 if (!opt_effect) opt_effect = new ImageView.Effect.None(); |
| 671 if (opt_duration == undefined) | |
|
dgozman
2012/09/14 15:17:38
I'd use typeof(opt_duration) == "number"
| |
| 672 element.style.webkitTransitionDuration = ''; // Use CSS-defined default. | |
| 673 else | |
| 674 element.style.webkitTransitionDuration = opt_duration + 'ms'; | |
| 662 element.style.webkitTransform = opt_effect.transform(element, this.viewport_); | 675 element.style.webkitTransform = opt_effect.transform(element, this.viewport_); |
| 663 }; | 676 }; |
| 664 | 677 |
| 665 /** | 678 /** |
| 666 * @param {Rect} screenRect Target rectangle in screen coordinates. | 679 * @param {Rect} screenRect Target rectangle in screen coordinates. |
| 667 * @return {ImageView.Effect.Zoom} Zoom effect object. | 680 * @return {ImageView.Effect.Zoom} Zoom effect object. |
| 668 */ | 681 */ |
| 669 ImageView.prototype.createZoomEffect = function(screenRect) { | 682 ImageView.prototype.createZoomEffect = function(screenRect) { |
| 670 return new ImageView.Effect.Zoom( | 683 return new ImageView.Effect.Zoom( |
| 671 this.viewport_.screenToDeviceRect(screenRect)); | 684 this.viewport_.screenToDeviceRect(screenRect), |
| 685 null /* use viewport */, | |
| 686 ImageView.ZOOM_ANIMATION_DURATION); | |
| 672 }; | 687 }; |
| 673 | 688 |
| 674 /** | 689 /** |
| 675 * Visualize crop or rotate operation. Hide the old image instantly, animate | 690 * Visualize crop or rotate operation. Hide the old image instantly, animate |
| 676 * the new image to visualize the operation. | 691 * the new image to visualize the operation. |
| 677 * | 692 * |
| 678 * @param {HTMLCanvasElement} canvas New content canvas. | 693 * @param {HTMLCanvasElement} canvas New content canvas. |
| 679 * @param {Rect} imageCropRect The crop rectangle in image coordinates. | 694 * @param {Rect} imageCropRect The crop rectangle in image coordinates. |
| 680 * Null for rotation operations. | 695 * Null for rotation operations. |
| 681 * @param {number} rotate90 Rotation angle in 90 degree increments. | 696 * @param {number} rotate90 Rotation angle in 90 degree increments. |
| 682 */ | 697 */ |
| 683 ImageView.prototype.replaceAndAnimate = function( | 698 ImageView.prototype.replaceAndAnimate = function( |
| 684 canvas, imageCropRect, rotate90) { | 699 canvas, imageCropRect, rotate90) { |
| 685 var oldScale = this.viewport_.getScale(); | 700 var oldScale = this.viewport_.getScale(); |
| 686 var deviceCropRect = imageCropRect && this.viewport_.screenToDeviceRect( | 701 var deviceCropRect = imageCropRect && this.viewport_.screenToDeviceRect( |
| 687 this.viewport_.imageToScreenRect(imageCropRect)); | 702 this.viewport_.imageToScreenRect(imageCropRect)); |
| 688 | 703 |
| 689 var oldScreenImage = this.screenImage_; | 704 var oldScreenImage = this.screenImage_; |
| 690 this.replaceContent_(canvas); | 705 this.replaceContent_(canvas); |
| 691 var newScreenImage = this.screenImage_; | 706 var newScreenImage = this.screenImage_; |
| 692 | 707 |
| 693 // Display the new canvas, initially transformed. | 708 // Display the new canvas, initially transformed. |
| 694 var deviceFullRect = this.viewport_.getDeviceClipped(); | 709 var deviceFullRect = this.viewport_.getDeviceClipped(); |
| 695 | 710 |
| 696 //Transform instantly. | |
| 697 newScreenImage.style.webkitTransitionDuration = '0ms'; | |
| 698 this.setTransform(newScreenImage, rotate90 ? | 711 this.setTransform(newScreenImage, rotate90 ? |
| 699 new ImageView.Effect.Rotate( | 712 new ImageView.Effect.Rotate( |
| 700 oldScale / this.viewport_.getScale(), -rotate90) : | 713 oldScale / this.viewport_.getScale(), -rotate90) : |
| 701 new ImageView.Effect.Zoom(deviceCropRect, deviceFullRect)); | 714 new ImageView.Effect.Zoom(deviceCropRect, deviceFullRect), |
| 715 0 /* Transform instantly*/); | |
| 702 | 716 |
| 703 oldScreenImage.parentNode.appendChild(newScreenImage); | 717 oldScreenImage.parentNode.appendChild(newScreenImage); |
| 704 oldScreenImage.parentNode.removeChild(oldScreenImage); | 718 oldScreenImage.parentNode.removeChild(oldScreenImage); |
| 705 | 719 |
| 706 // Let the layout fire. | 720 // Let the layout fire, then animate back to non-transformed state. |
| 707 setTimeout(function() { | 721 setTimeout(this.setTransform.bind(this, newScreenImage), 0); |
| 708 // Animated back to non-transformed state. | |
| 709 newScreenImage.style.webkitTransitionDuration = ''; | |
| 710 this.setTransform(newScreenImage); | |
| 711 }.bind(this), 0); | |
| 712 }; | 722 }; |
| 713 | 723 |
| 714 /** | 724 /** |
| 715 * Visualize "undo crop". Shrink the current image to the given crop rectangle | 725 * Visualize "undo crop". Shrink the current image to the given crop rectangle |
| 716 * while fading in the new image. | 726 * while fading in the new image. |
| 717 * | 727 * |
| 718 * @param {HTMLCanvasElement} canvas New content canvas. | 728 * @param {HTMLCanvasElement} canvas New content canvas. |
| 719 * @param {Rect} imageCropRect The crop rectangle in image coordinates. | 729 * @param {Rect} imageCropRect The crop rectangle in image coordinates. |
| 720 */ | 730 */ |
| 721 ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) { | 731 ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) { |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 889 | 899 |
| 890 /** | 900 /** |
| 891 * Zoom effect. | 901 * Zoom effect. |
| 892 * | 902 * |
| 893 * Animates the original rectangle to the target rectangle. Both parameters | 903 * Animates the original rectangle to the target rectangle. Both parameters |
| 894 * should be given in device coordinates (accounting for devicePixelRatio). | 904 * should be given in device coordinates (accounting for devicePixelRatio). |
| 895 * | 905 * |
| 896 * @param {Rect} deviceTargetRect Target rectangle. | 906 * @param {Rect} deviceTargetRect Target rectangle. |
| 897 * @param {Rect} opt_deviceOriginalRect Original rectangle. If omitted, | 907 * @param {Rect} opt_deviceOriginalRect Original rectangle. If omitted, |
| 898 * the full viewport will be used at the time of |transform| call. | 908 * the full viewport will be used at the time of |transform| call. |
| 909 * @param {number} opt_duration Duration in ms. | |
| 899 * @constructor | 910 * @constructor |
| 900 */ | 911 */ |
| 901 ImageView.Effect.Zoom = function(deviceTargetRect, opt_deviceOriginalRect) { | 912 ImageView.Effect.Zoom = function( |
| 913 deviceTargetRect, opt_deviceOriginalRect, opt_duration) { | |
| 902 this.target_ = deviceTargetRect; | 914 this.target_ = deviceTargetRect; |
| 903 this.original_ = opt_deviceOriginalRect; | 915 this.original_ = opt_deviceOriginalRect; |
| 916 this.duration = opt_duration; | |
| 904 }; | 917 }; |
| 905 | 918 |
| 906 /** | 919 /** |
| 907 * @param {HTMLCanvasElement|HTMLVideoElement} element Element. | 920 * @param {HTMLCanvasElement|HTMLVideoElement} element Element. |
| 908 * @param {Viewport} viewport Viewport. | 921 * @param {Viewport} viewport Viewport. |
| 909 * @return {string} Transform string. | 922 * @return {string} Transform string. |
| 910 */ | 923 */ |
| 911 ImageView.Effect.Zoom.prototype.transform = function(element, viewport) { | 924 ImageView.Effect.Zoom.prototype.transform = function(element, viewport) { |
| 912 if (!this.original_) | 925 if (!this.original_) |
| 913 this.original_ = viewport.getDeviceClipped(); | 926 this.original_ = viewport.getDeviceClipped(); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 940 | 953 |
| 941 /** | 954 /** |
| 942 * @param {HTMLCanvasElement|HTMLVideoElement} element Element. | 955 * @param {HTMLCanvasElement|HTMLVideoElement} element Element. |
| 943 * @return {string} Transform string. | 956 * @return {string} Transform string. |
| 944 */ | 957 */ |
| 945 ImageView.Effect.Rotate.prototype.transform = function(element) { | 958 ImageView.Effect.Rotate.prototype.transform = function(element) { |
| 946 var ratio = ImageView.Effect.getPixelRatio_(element); | 959 var ratio = ImageView.Effect.getPixelRatio_(element); |
| 947 return 'rotate(' + (this.rotate90_ * 90) + 'deg) ' + | 960 return 'rotate(' + (this.rotate90_ * 90) + 'deg) ' + |
| 948 'scale(' + (this.scale_ / ratio) + ')'; | 961 'scale(' + (this.scale_ / ratio) + ')'; |
| 949 }; | 962 }; |
| OLD | NEW |