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

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

Issue 384573002: Gallery.app: Move geometry calculation for the slide image to Viewport class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | ui/file_manager/gallery/js/image_editor/viewport.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 'use strict'; 5 'use strict';
6 6
7 /** 7 /**
8 * The overlay displaying the image. 8 * The overlay displaying the image.
9 * 9 *
10 * @param {HTMLElement} container The container element. 10 * @param {HTMLElement} container The container element.
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 element.style.webkitTransitionDuration = opt_duration + 'ms'; 619 element.style.webkitTransitionDuration = opt_duration + 'ms';
620 element.style.webkitTransitionTimingFunction = opt_effect.getTiming(); 620 element.style.webkitTransitionTimingFunction = opt_effect.getTiming();
621 element.style.webkitTransform = opt_effect.transform(element, this.viewport_); 621 element.style.webkitTransform = opt_effect.transform(element, this.viewport_);
622 }; 622 };
623 623
624 /** 624 /**
625 * @param {Rect} screenRect Target rectangle in screen coordinates. 625 * @param {Rect} screenRect Target rectangle in screen coordinates.
626 * @return {ImageView.Effect.Zoom} Zoom effect object. 626 * @return {ImageView.Effect.Zoom} Zoom effect object.
627 */ 627 */
628 ImageView.prototype.createZoomEffect = function(screenRect) { 628 ImageView.prototype.createZoomEffect = function(screenRect) {
629 return new ImageView.Effect.Zoom( 629 return new ImageView.Effect.ZoomToScreen(
630 this.viewport_.screenToDeviceRect(screenRect), 630 screenRect,
631 null /* use viewport */,
632 ImageView.MODE_TRANSITION_DURATION); 631 ImageView.MODE_TRANSITION_DURATION);
633 }; 632 };
634 633
635 /** 634 /**
636 * Visualizes crop or rotate operation. Hide the old image instantly, animate 635 * Visualizes crop or rotate operation. Hide the old image instantly, animate
637 * the new image to visualize the operation. 636 * the new image to visualize the operation.
638 * 637 *
639 * @param {HTMLCanvasElement} canvas New content canvas. 638 * @param {HTMLCanvasElement} canvas New content canvas.
640 * @param {Rect} imageCropRect The crop rectangle in image coordinates. 639 * @param {Rect} imageCropRect The crop rectangle in image coordinates.
641 * Null for rotation operations. 640 * Null for rotation operations.
642 * @param {number} rotate90 Rotation angle in 90 degree increments. 641 * @param {number} rotate90 Rotation angle in 90 degree increments.
643 * @return {number} Animation duration. 642 * @return {number} Animation duration.
644 */ 643 */
645 ImageView.prototype.replaceAndAnimate = function( 644 ImageView.prototype.replaceAndAnimate = function(
646 canvas, imageCropRect, rotate90) { 645 canvas, imageCropRect, rotate90) {
647 var oldScale = this.viewport_.getScale(); 646 var oldImageBounds = {
648 var deviceCropRect = imageCropRect && this.viewport_.screenToDeviceRect( 647 width: this.viewport_.getImageBounds().width,
649 this.viewport_.imageToScreenRect(imageCropRect)); 648 height: this.viewport_.getImageBounds().height
650 649 };
651 var oldScreenImage = this.screenImage_; 650 var oldScreenImage = this.screenImage_;
652 this.replaceContent_(canvas); 651 this.replaceContent_(canvas);
653 var newScreenImage = this.screenImage_; 652 var newScreenImage = this.screenImage_;
654
655 // Display the new canvas, initially transformed.
656 var deviceFullRect = this.viewport_.getDeviceClipped();
657
658 var effect = rotate90 ? 653 var effect = rotate90 ?
659 new ImageView.Effect.Rotate( 654 new ImageView.Effect.Rotate(rotate90 > 0) :
660 oldScale / this.viewport_.getScale(), -rotate90) : 655 new ImageView.Effect.Zoom(
661 new ImageView.Effect.Zoom(deviceCropRect, deviceFullRect); 656 oldImageBounds.width, oldImageBounds.height, imageCropRect);
662 657
663 this.setTransform(newScreenImage, effect, 0 /* instant */); 658 this.setTransform(newScreenImage, effect, 0 /* instant */);
664 659
665 oldScreenImage.parentNode.appendChild(newScreenImage); 660 oldScreenImage.parentNode.appendChild(newScreenImage);
666 oldScreenImage.parentNode.removeChild(oldScreenImage); 661 oldScreenImage.parentNode.removeChild(oldScreenImage);
667 662
668 // Let the layout fire, then animate back to non-transformed state. 663 // Let the layout fire, then animate back to non-transformed state.
669 setTimeout( 664 setTimeout(
670 this.setTransform.bind( 665 this.setTransform.bind(
671 this, newScreenImage, null, effect.getDuration()), 666 this, newScreenImage, null, effect.getDuration()),
672 0); 667 0);
673 668
674 return effect.getSafeInterval(); 669 return effect.getSafeInterval();
675 }; 670 };
676 671
677 /** 672 /**
678 * Visualizes "undo crop". Shrink the current image to the given crop rectangle 673 * Visualizes "undo crop". Shrink the current image to the given crop rectangle
679 * while fading in the new image. 674 * while fading in the new image.
680 * 675 *
681 * @param {HTMLCanvasElement} canvas New content canvas. 676 * @param {HTMLCanvasElement} canvas New content canvas.
682 * @param {Rect} imageCropRect The crop rectangle in image coordinates. 677 * @param {Rect} imageCropRect The crop rectangle in image coordinates.
683 * @return {number} Animation duration. 678 * @return {number} Animation duration.
684 */ 679 */
685 ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) { 680 ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) {
686 var deviceFullRect = this.viewport_.getDeviceClipped();
687 var oldScale = this.viewport_.getScale();
688
689 var oldScreenImage = this.screenImage_; 681 var oldScreenImage = this.screenImage_;
690 this.replaceContent_(canvas); 682 this.replaceContent_(canvas);
691 var newScreenImage = this.screenImage_; 683 var newScreenImage = this.screenImage_;
692
693 var deviceCropRect = this.viewport_.screenToDeviceRect(
694 this.viewport_.imageToScreenRect(imageCropRect));
695
696 var setFade = ImageUtil.setAttribute.bind(null, newScreenImage, 'fade'); 684 var setFade = ImageUtil.setAttribute.bind(null, newScreenImage, 'fade');
697 setFade(true); 685 setFade(true);
698 oldScreenImage.parentNode.insertBefore(newScreenImage, oldScreenImage); 686 oldScreenImage.parentNode.insertBefore(newScreenImage, oldScreenImage);
687 var effect = new ImageView.Effect.Zoom(
688 this.viewport_.getImageBounds().width,
689 this.viewport_.getImageBounds().height,
690 imageCropRect);
699 691
700 var effect = new ImageView.Effect.Zoom(deviceCropRect, deviceFullRect);
701 // Animate to the transformed state. 692 // Animate to the transformed state.
702 this.setTransform(oldScreenImage, effect); 693 this.setTransform(oldScreenImage, effect);
703
704 setTimeout(setFade.bind(null, false), 0); 694 setTimeout(setFade.bind(null, false), 0);
705
706 setTimeout(function() { 695 setTimeout(function() {
707 if (oldScreenImage.parentNode) 696 if (oldScreenImage.parentNode)
708 oldScreenImage.parentNode.removeChild(oldScreenImage); 697 oldScreenImage.parentNode.removeChild(oldScreenImage);
709 }, effect.getSafeInterval()); 698 }, effect.getSafeInterval());
710 699
711 return effect.getSafeInterval(); 700 return effect.getSafeInterval();
712 }; 701 };
713 702
714
715 /** 703 /**
716 * Generic cache with a limited capacity and LRU eviction. 704 * Generic cache with a limited capacity and LRU eviction.
717 * @param {number} capacity Maximum number of cached item. 705 * @param {number} capacity Maximum number of cached item.
718 * @constructor 706 * @constructor
719 */ 707 */
720 ImageView.Cache = function(capacity) { 708 ImageView.Cache = function(capacity) {
721 this.capacity_ = capacity; 709 this.capacity_ = capacity;
722 this.map_ = {}; 710 this.map_ = {};
723 this.order_ = []; 711 this.order_ = [];
724 }; 712 };
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 ImageView.Effect.prototype.getSafeInterval = function() { 833 ImageView.Effect.prototype.getSafeInterval = function() {
846 return this.getDuration() + ImageView.Effect.MARGIN; 834 return this.getDuration() + ImageView.Effect.MARGIN;
847 }; 835 };
848 836
849 /** 837 /**
850 * @return {string} CSS transition timing function name. 838 * @return {string} CSS transition timing function name.
851 */ 839 */
852 ImageView.Effect.prototype.getTiming = function() { return this.timing_; }; 840 ImageView.Effect.prototype.getTiming = function() { return this.timing_; };
853 841
854 /** 842 /**
855 * @param {HTMLCanvasElement} element Element. 843 * Obtains the CSS transformation string of the effect.
856 * @return {number} Preferred pixel ration to use with this element. 844 * @param {DOMCanvas} element Canvas element to be applied the transforamtion.
857 * @private 845 * @param {Viewport} viewport Current viewport.
846 * @return CSS transformation description.
858 */ 847 */
859 ImageView.Effect.getPixelRatio_ = function(element) { 848 ImageView.Effect.prototype.transform = function(element, viewport) {
860 if (element.constructor.name === 'HTMLCanvasElement') 849 throw new Error('Not implemented.');
861 return Viewport.getDevicePixelRatio();
862 else
863 return 1;
864 }; 850 };
865 851
866 /** 852 /**
867 * Default effect. It is not a no-op as it needs to adjust a canvas scale 853 * Default effect. It is not a no-op as it needs to adjust a canvas scale
868 * for devicePixelRatio. 854 * for devicePixelRatio.
869 * 855 *
870 * @constructor 856 * @constructor
857 * @extends {ImageView.Effect}
871 */ 858 */
872 ImageView.Effect.None = function() { 859 ImageView.Effect.None = function() {
873 ImageView.Effect.call(this, 0); 860 ImageView.Effect.call(this, 0);
874 }; 861 };
875 862
876 /** 863 /**
877 * Inherits from ImageView.Effect. 864 * Inherits from ImageView.Effect.
878 */ 865 */
879 ImageView.Effect.None.prototype = { __proto__: ImageView.Effect.prototype }; 866 ImageView.Effect.None.prototype = { __proto__: ImageView.Effect.prototype };
880 867
881 /** 868 /**
882 * @param {HTMLCanvasElement} element Element. 869 * @param {HTMLCanvasElement} element Element.
870 * @param {Viewport} viewport Current viewport.
883 * @return {string} Transform string. 871 * @return {string} Transform string.
884 */ 872 */
885 ImageView.Effect.None.prototype.transform = function(element) { 873 ImageView.Effect.None.prototype.transform = function(element, viewport) {
886 var ratio = ImageView.Effect.getPixelRatio_(element); 874 return viewport.getTransformation();
887 return 'scale(' + (1 / ratio) + ')';
888 }; 875 };
889 876
890 /** 877 /**
891 * Slide effect. 878 * Slide effect.
892 * 879 *
893 * @param {number} direction -1 for left, 1 for right. 880 * @param {number} direction -1 for left, 1 for right.
894 * @param {boolean=} opt_slow True if slow (as in slideshow). 881 * @param {boolean=} opt_slow True if slow (as in slideshow).
895 * @constructor 882 * @constructor
883 * @extends {ImageView.Effect}
896 */ 884 */
897 ImageView.Effect.Slide = function Slide(direction, opt_slow) { 885 ImageView.Effect.Slide = function Slide(direction, opt_slow) {
898 ImageView.Effect.call(this, 886 ImageView.Effect.call(this,
899 opt_slow ? 800 : ImageView.Effect.DEFAULT_DURATION, 'ease-in-out'); 887 opt_slow ? 800 : ImageView.Effect.DEFAULT_DURATION, 'ease-in-out');
900 this.direction_ = direction; 888 this.direction_ = direction;
901 this.slow_ = opt_slow; 889 this.slow_ = opt_slow;
902 this.shift_ = opt_slow ? 100 : 40; 890 this.shift_ = opt_slow ? 100 : 40;
903 if (this.direction_ < 0) this.shift_ = -this.shift_; 891 if (this.direction_ < 0) this.shift_ = -this.shift_;
904 }; 892 };
905 893
906 /**
907 * Inherits from ImageView.Effect.
908 */
909 ImageView.Effect.Slide.prototype = { __proto__: ImageView.Effect.prototype }; 894 ImageView.Effect.Slide.prototype = { __proto__: ImageView.Effect.prototype };
910 895
911 /** 896 /**
912 * @return {ImageView.Effect.Slide} Reverse Slide effect. 897 * Reverses the slide effect.
898 * @return {ImageView.Effect.Slide} Reversed effect.
913 */ 899 */
914 ImageView.Effect.Slide.prototype.getReverse = function() { 900 ImageView.Effect.Slide.prototype.getReverse = function() {
915 return new ImageView.Effect.Slide(-this.direction_, this.slow_); 901 return new ImageView.Effect.Slide(-this.direction_, this.slow_);
916 }; 902 };
917 903
918 /** 904 /**
919 * @param {HTMLCanvasElement} element Element. 905 * @override
920 * @return {string} Transform string.
921 */ 906 */
922 ImageView.Effect.Slide.prototype.transform = function(element) { 907 ImageView.Effect.Slide.prototype.transform = function(element, viewport) {
923 var ratio = ImageView.Effect.getPixelRatio_(element); 908 return viewport.getShiftTransformation(this.shift_);
924 return 'scale(' + (1 / ratio) + ') translate(' + this.shift_ + 'px, 0px)';
925 }; 909 };
926 910
927 /** 911 /**
928 * Zoom effect. 912 * Zoom effect.
929 * 913 *
930 * Animates the original rectangle to the target rectangle. Both parameters 914 * Animates the original rectangle to the target rectangle. Both parameters
931 * should be given in device coordinates (accounting for devicePixelRatio). 915 * should be given in device coordinates (accounting for devicePixelRatio).
932 * 916 *
933 * @param {Rect} deviceTargetRect Target rectangle. 917 * @param {number} previousImageWidth Width of the full resolution image.
934 * @param {Rect=} opt_deviceOriginalRect Original rectangle. If omitted, 918 * @param {number} previousImageHeight Hieght of the full resolution image.
935 * the full viewport will be used at the time of |transform| call. 919 * @param {Rect} imageCropRect Crop rectangle in the full resolution image.
936 * @param {number=} opt_duration Duration in ms. 920 * @param {number=} opt_duration Duration of the effect.
937 * @constructor 921 * @constructor
922 * @extends {ImageView.Effect}
938 */ 923 */
939 ImageView.Effect.Zoom = function( 924 ImageView.Effect.Zoom = function(
940 deviceTargetRect, opt_deviceOriginalRect, opt_duration) { 925 previousImageWidth, previousImageHeight, imageCropRect, opt_duration) {
941 ImageView.Effect.call(this, 926 ImageView.Effect.call(this,
942 opt_duration || ImageView.Effect.DEFAULT_DURATION); 927 opt_duration || ImageView.Effect.DEFAULT_DURATION);
943 this.target_ = deviceTargetRect; 928 this.previousImageWidth_ = previousImageWidth;
944 this.original_ = opt_deviceOriginalRect; 929 this.previousImageHeight_ = previousImageHeight;
930 this.imageCropRect_ = imageCropRect;
931 };
932
933 ImageView.Effect.Zoom.prototype = { __proto__: ImageView.Effect.prototype };
934
935 /**
936 * @override
937 */
938 ImageView.Effect.Zoom.prototype.transform = function(element, viewport) {
939 return viewport.getInverseTransformForCroppedImage(
940 this.previousImageWidth_, this.previousImageHeight_, this.imageCropRect_);
945 }; 941 };
946 942
947 /** 943 /**
948 * Inherits from ImageView.Effect. 944 * Effect to zoom to a screen rectangle.
945 *
946 * @param {Rect} screenRect Rectangle in the application window's coordinate.
947 * @param {number=} opt_duration Duration of effect.
948 * @constructor
949 * @extends {ImageView.Effect}
949 */ 950 */
950 ImageView.Effect.Zoom.prototype = { __proto__: ImageView.Effect.prototype }; 951 ImageView.Effect.ZoomToScreen = function(screenRect, opt_duration) {
952 ImageView.Effect.call(this, opt_duration);
953 this.screenRect_ = screenRect;
954 };
951 955
952 /** 956 ImageView.Effect.ZoomToScreen.prototype = {
953 * @param {HTMLCanvasElement} element Element. 957 __proto__: ImageView.Effect.prototype
954 * @param {Viewport} viewport Viewport.
955 * @return {string} Transform string.
956 */
957 ImageView.Effect.Zoom.prototype.transform = function(element, viewport) {
958 if (!this.original_)
959 this.original_ = viewport.getDeviceClipped();
960
961 var ratio = ImageView.Effect.getPixelRatio_(element);
962
963 var dx = (this.target_.left + this.target_.width / 2) -
964 (this.original_.left + this.original_.width / 2);
965 var dy = (this.target_.top + this.target_.height / 2) -
966 (this.original_.top + this.original_.height / 2);
967
968 var scaleX = this.target_.width / this.original_.width;
969 var scaleY = this.target_.height / this.original_.height;
970
971 return 'translate(' + (dx / ratio) + 'px,' + (dy / ratio) + 'px) ' +
972 'scaleX(' + (scaleX / ratio) + ') scaleY(' + (scaleY / ratio) + ')';
973 }; 958 };
974 959
975 /** 960 /**
976 * Rotate effect. 961 * @override
977 *
978 * @param {number} scale Scale.
979 * @param {number} rotate90 Rotation in 90 degrees increments.
980 * @constructor
981 */ 962 */
982 ImageView.Effect.Rotate = function(scale, rotate90) { 963 ImageView.Effect.ZoomToScreen.prototype.transform = function(
983 ImageView.Effect.call(this, ImageView.Effect.DEFAULT_DURATION); 964 element, viewport) {
984 this.scale_ = scale; 965 return viewport.getScreenRectTransformForImage(this.screenRect_);
985 this.rotate90_ = rotate90;
986 }; 966 };
987 967
988 /** 968 /**
989 * Inherits from ImageView.Effect. 969 * Rotation effect.
970 *
971 * @param {boolean} orientation Orientation of rotation. True is for clockwise
972 * and false is for counterclockwise.
973 * @constructor
974 * @extends {ImageView.Effect}
990 */ 975 */
976 ImageView.Effect.Rotate = function(orientation) {
977 ImageView.Effect.call(this, ImageView.Effect.DEFAULT_DURATION);
978 this.orientation_ = orientation;
979 };
980
991 ImageView.Effect.Rotate.prototype = { __proto__: ImageView.Effect.prototype }; 981 ImageView.Effect.Rotate.prototype = { __proto__: ImageView.Effect.prototype };
992 982
993 /** 983 /**
994 * @param {HTMLCanvasElement} element Element. 984 * @override
995 * @return {string} Transform string.
996 */ 985 */
997 ImageView.Effect.Rotate.prototype.transform = function(element) { 986 ImageView.Effect.Rotate.prototype.transform = function(element, viewport) {
998 var ratio = ImageView.Effect.getPixelRatio_(element); 987 return viewport.getInverseTransformForRotatedImage(this.orientation_);
999 return 'rotate(' + (this.rotate90_ * 90) + 'deg) ' +
1000 'scale(' + (this.scale_ / ratio) + ')';
1001 }; 988 };
OLDNEW
« no previous file with comments | « no previous file | ui/file_manager/gallery/js/image_editor/viewport.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698