1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2006-2009 Sprout Systems, Inc. and contributors. 4 // Portions ©2010-2011 Strobe Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 8 sc_require('render_delegates/render_delegate'); 9 10 /** 11 @class 12 Renders and updates DOM representations of an image. 13 14 Parameters 15 -------------------------- 16 Expects these properties on the data source: 17 18 - image: An Image object which has completed loading 19 20 If any of these are not present in the data source, the render delegate 21 will throw an error. 22 23 Optional Parameters: 24 --------------------------- 25 If present, these properties will be used. 26 27 - width: Used on the canvas element. If not provided, 0 is used and the canvas 28 will not be visible. 29 - height: Used on the canvas element. If not provided, 0 is used and the canvas 30 will not be visible. 31 - scale: If provided, the image will maintain aspect ratio as specified by this 32 property. One of 33 - SC.SCALE_NONE 34 - SC.FILL 35 - SC.BEST_FILL 36 - SC.BEST_FIT 37 - SC.BEST_FIT_DOWN_ONLY 38 - percentage {Number} 39 If not provided, SC.FILL will be the default (ie. expected image behaviour) 40 - align: If provided, the image will align itself within its frame. One of 41 - SC.ALIGN_CENTER 42 - SC.ALIGN_TOP_LEFT 43 - SC.ALIGN_TOP 44 - SC.ALIGN_TOP_RIGHT 45 - SC.ALIGN_RIGHT 46 - SC.ALIGN_BOTTOM_RIGHT 47 - SC.ALIGN_BOTTOM 48 - SC.ALIGN_BOTTOM_LEFT 49 - SC.ALIGN_LEFT 50 - backgroundColor: If provided, the canvas will render a backgroundColor 51 */ 52 53 SC.BaseTheme.canvasImageRenderDelegate = SC.RenderDelegate.create({ 54 className: 'canvasImage', 55 56 /** @private 57 We don't have an element yet, so we do the minimal necessary setup 58 here. 59 */ 60 render: function (dataSource, context) { 61 var width = dataSource.get('width') || 0, 62 height = dataSource.get('height') || 0, 63 type = dataSource.get('type') || SC.IMAGE_TYPE_URL, 64 value = dataSource.get('value'); 65 66 // Support for CSS sprites (TODO: Remove this) 67 if (value && type === SC.IMAGE_TYPE_CSS_CLASS) { 68 context.addClass(value); 69 dataSource.renderState._last_class = value; 70 } 71 72 context.setAttr('width', width); 73 context.setAttr('height', height); 74 }, 75 76 update: function (dataSource, jquery) { 77 var elem = jquery[0], 78 image = dataSource.get('image'), 79 frame = dataSource.get('frame'), 80 frameWidth = frame.width, 81 frameHeight = frame.height, 82 innerFrame = dataSource.get('innerFrame'), 83 backgroundColor = dataSource.get('backgroundColor'), 84 renderState = dataSource.get('renderState'), 85 context, 86 lastClass = dataSource.renderState._last_class, 87 type = dataSource.get('type') || SC.IMAGE_TYPE_URL, 88 value = dataSource.get('value'); 89 90 // Support for CSS sprites 91 if (lastClass) jquery.removeClass(lastClass); 92 if (value && type === SC.IMAGE_TYPE_CSS_CLASS) { 93 jquery.addClass(value); 94 dataSource.renderState._last_class = value; 95 96 // Clear the context in case there was a URL previously 97 if (elem && elem.getContext) { 98 context = elem.getContext('2d'); 99 context.clearRect(0, 0, frameWidth, frameHeight); 100 } 101 } else { 102 103 // We only care about specific values, check specifically for what matters 104 var innerFrameDidChange = ![innerFrame.x, innerFrame.y, innerFrame.width, innerFrame.height].isEqual(renderState._lastInnerFrameValues), 105 elemSizeDidChange = ![elem.width, elem.height].isEqual(renderState._lastElemSizeValues), 106 backgroundDidChange = dataSource.didChangeFor('canvasImageRenderDelegate', 'backgroundColor'), 107 imageDidChange = dataSource.didChangeFor('canvasImageRenderDelegate', 'image') || (image && image.complete) !== renderState._lastImageComplete; 108 109 if (elemSizeDidChange || innerFrameDidChange || backgroundDidChange || imageDidChange) { 110 111 if (elem && elem.getContext) { 112 elem.height = frameHeight; 113 elem.width = frameWidth; 114 115 context = elem.getContext('2d'); 116 117 context.clearRect(0, 0, frameWidth, frameHeight); 118 119 if (backgroundColor) { 120 context.fillStyle = backgroundColor; 121 context.fillRect(0, 0, frameWidth, frameHeight); 122 } 123 124 if (image && image.complete) { 125 context.drawImage(image, Math.floor(innerFrame.x), Math.floor(innerFrame.y), Math.floor(innerFrame.width), Math.floor(innerFrame.height)); 126 } 127 } 128 129 // Update caches 130 renderState._lastInnerFrameValues = [innerFrame.x, innerFrame.y, innerFrame.width, innerFrame.height]; 131 renderState._lastElemSizeValues = [elem.width, elem.height]; 132 renderState._lastImageComplete = image && image.complete; 133 } 134 } 135 } 136 137 }); 138