var CanvasRenderingTool = function(config, target){ var events = new EventManager, context = target.getContext('2d'), adBrand = undefined, adWidth = undefined, adHeight = undefined, status = false, maxTextWidth = 188, clickItems = undefined, hoverItems = undefined, activeHover = [], dragFocus = undefined, dragStart = undefined, dragEnd = undefined, dragState = false, dragStateTypes = { 'background' : true }, fileInput = undefined, fileInputData = undefined, fileInputCallback = undefined, proxyURL = '//panda.meteora.us/proxy?url=', viewFrame = config.viewFrame, dataArray = undefined, frameActions = undefined; if(config) init(); else console.error('Error, no config'); this.getData = function(){ return dataArray; }; this.getImage = function(view){ if(!view) return target.toDataURL('image/png'); else { var currentViewframe = viewFrame, imageData = undefined; viewFrame = view; imageData = cycle(true); viewFrame = currentViewframe; return imageData; } }; this.run = function(data){ if(status == true) run(data); else return false; }; this.setView = function(view){ viewFrame = view; cycle(); }; this.updateData = updateData; this.exit = exit; function init(){ adWidth = target.width = config.width; adHeight = target.height = config.height; bindCanvas(); fileInput = createFileInput(); fileInput.onchange = function(e){ new FileToImageData(fileInput, fileInputCallback); }; status = true; } function run(data, update){ var imageCount = 0, loadCount = 0; for(var i=0, l=data.length; i 0) run(a, true); } function clearFrameActions(){ dragFocus = undefined; clickItems = undefined; } function clearStage(){ context.clearRect(0, 0, adWidth, adHeight); } function updateStage(img){ context.drawImage(img, 0, 0, adWidth, adHeight); } function createOffstage(){ var offStage = document.createElement('canvas'); offStage.width = adWidth; offStage.height = adHeight; return offStage; } function createRect(obj){ var rectCanvas = document.createElement('canvas'), rectContext = rectCanvas.getContext('2d'), width = obj.width, height = obj.height, padding = obj.padding ? obj.padding : [0,0,0,0], shadow = obj.shadow; rectCanvas.width = width + padding[1] + padding[3]; rectCanvas.height = height + padding[0] + padding[2]; if(shadow){ rectContext.shadowOffsetX = shadow.offsetX; rectContext.shadowOffsetY = shadow.offsetY; rectContext.shadowBlur = shadow.blur; rectContext.shadowColor = shadow.color; } rectContext.fillStyle = obj.fill; rectContext.fillRect(padding[0], padding[3], width, height); obj.img = rectCanvas; } function createRoundedRect(obj){ var rectCanvas = document.createElement('canvas'), rectContext = rectCanvas.getContext('2d'), width = obj.width, height = obj.height, padding = obj.padding ? obj.padding : [0,0,0,0], shadow = obj.shadow, stroke = obj.stroke, radius = obj.radius, fill = obj.fill; if(stroke == undefined) stroke = true; if(radius == undefined) radius = 6; rectCanvas.width = width + padding[1] + padding[3]; rectCanvas.height = height + padding[0] + padding[2]; if(shadow){ rectContext.shadowOffsetX = shadow.offsetX; rectContext.shadowOffsetY = shadow.offsetY; rectContext.shadowBlur = shadow.blur; rectContext.shadowColor = shadow.color; } var x = padding[3], y = padding[0]; rectContext.beginPath(); rectContext.moveTo(x + radius, y); rectContext.lineTo(x + width - radius, y); rectContext.quadraticCurveTo(x + width, y, x + width, y + radius); rectContext.lineTo(x + width, y + height - radius); rectContext.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); rectContext.lineTo(x + radius, y + height); rectContext.quadraticCurveTo(x, y + height, x, y + height - radius); rectContext.lineTo(x, y + radius); rectContext.quadraticCurveTo(x, y, x + radius, y); rectContext.closePath(); if(stroke) rectContext.stroke(); if(fill){ rectContext.fillStyle = fill; rectContext.fill(); } obj.img = rectCanvas; } function roundRect(ctx, x, y, width, height, radius, fill, stroke) { ctx.beginPath(); ctx.moveTo(x + radius, y); ctx.lineTo(x + width - radius, y); ctx.quadraticCurveTo(x + width, y, x + width, y + radius); ctx.lineTo(x + width, y + height - radius); ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); ctx.lineTo(x + radius, y + height); ctx.quadraticCurveTo(x, y + height, x, y + height - radius); ctx.lineTo(x, y + radius); ctx.quadraticCurveTo(x, y, x + radius, y); ctx.closePath(); if(stroke) ctx.stroke(); if(fill) ctx.fill(); } function createPath(obj){ var pathCanvas = document.createElement('canvas'), pathContext = pathCanvas.getContext('2d'); pathCanvas.width = obj.width; pathCanvas.height = obj.height; pathContext.fillStyle = obj.fill; pathContext.beginPath(); for(var i=0, l=obj.path.length; i postContentTextLength) return postContentTextLength; else return postContentText.lastIndexOf(' ', eP); } function getLineString(charIndex){ var ls = postContentText.substring(charIndex, endPos); if(maxTextWidth < postContentContext.measureText(ls).width){ endPos = getEndPos(endPos - 1) ls = postContentText.substring(charIndex, endPos); } return ls; } } function renderSections(lineString, highlights, lineIndex){ var pos = padding[3], charIndex = 0, lineStringLength = lineString.length; if(highlights.length == 0) pos += renderNormal(lineIndex, pos, lineString); for(var i=0, l=highlights.length; i charIndex){ text = lineString.substring(charIndex, highlight.start); width = renderNormal(lineIndex, pos, text); pos += width; charIndex = highlight.start; } text = lineString.substring(highlight.start, highlight.end); width = renderHighlight(lineIndex, pos, text); pos += width; charIndex = highlight.end; if(i + 1 == l && highlight.end < lineStringLength){ text = lineString.substring(highlight.end, lineStringLength); width = renderNormal(lineIndex, pos, text); pos += width; charIndex = lineStringLength; } } return pos; } function renderNormal(lineIndex, pos, text){ var width = getTextWidth(postContentContext, fontString, text) postContentContext.fillText(text, pos, getFontPositioning(fontSize, lineHeight, lineIndex)); return width; } function getFontPositioning(fontSize, lineHeight, lineIndex){ var fs = fontSize, lhSize = fs * lineHeight; return (lhSize - ((lhSize - fs)/2)) * (1 + lineIndex); } function renderHighlight(lineIndex, pos, text){ postContentContext.save(); postContentContext.font = highlightFontString; postContentContext.fillStyle = highlightFillColor; postContentContext.fillText(text, pos, fontSize * (1 + lineIndex)); var width = getTextWidth(postContentContext, highlightFontString, text); postContentContext.restore(); return width; } function findHighlights(string){ var lcStr = string.toLowerCase(), startHighlight = undefined, endHighlight = undefined, matches = findMatches(); return matches; function findMatches(){ var array = []; for(var i=0, l=lcStr.length; i -1) array.push(obj); } return array; } } } } function createSocialIcon(obj, cb){ var src = obj.src, socialIconCanvas = document.createElement('canvas'), socialIconContext = socialIconCanvas.getContext('2d'), img = document.createElement('img'), width = 16, height = 16; socialIconCanvas.width = width; socialIconCanvasheight = height; obj.img = socialIconCanvas; img.onload = function(){ setTimeout(integrateImage, 1); }; img.onerror = function(){ cb(); }; img.src = '/public/images/adBuilder/social/' + src + '.png'; function integrateImage(){ socialIconContext.drawImage(img, 0, 0, width, height); cb(); } } function getProxySource(src){ var obj = { 'url' : src }; return proxyURL + encodeURIComponent(src); } function createCanvasImage(obj, cb, maintainScale){ var img = document.createElement('img'), backgroundCanvas = document.createElement('canvas'), backgroundContext = backgroundCanvas.getContext('2d'), src = obj.src, srcDefined = isDefined(src), domainMatch = srcDefined ? src.match(/[panda.meteora.us]{14}/) : null, dataMatch = srcDefined ? src.match(/[data:image]{10}/) : null; if(srcDefined){ if(domainMatch == null && dataMatch == null) src = getProxySource(src); events.add(img, 'load', imageReady); events.add(img, 'error', cb); img.src = src; } else if (!srcDefined) cb(); function imageReady(){ setTimeout(process, 1); } function process(){ var width = img.naturalWidth, height = img.naturalHeight, targetWidth = obj.width || adWidth, targetHeight = obj.height || adHeight, widthDelta = width / targetWidth, heightDelta = height / targetHeight, focusDelta = undefined, focusType = undefined, focusWidth = undefined, focusHeight = undefined, offsetX = 0, offsetY = 0; if(obj.movementX === undefined) obj.movementX = 0; if(obj.movementY === undefined) obj.movementY = 0; obj.update = cycle; if(maintainScale){ setFocusType(); setFocusRects(); setOffset(); } else { focusWidth = targetWidth; focusHeight = targetHeight; } setCanvasSizing(); updateObject(); cycle(); cb(); function setFocusType(){ if(widthDelta < heightDelta){ focusDelta = widthDelta; focusType = 'width'; } else { focusDelta = heightDelta; focusType = 'height'; } } function setFocusRects(){ if(focusDelta > 1) { focusWidth = width / focusDelta; focusHeight = height / focusDelta; } else { focusWidth = width; focusHeight = height; } } function setOffset(){ if(focusWidth < targetWidth) offsetX = (targetWidth - focusWidth) / 2; if(focusHeight < targetHeight) offsetY = (targetHeight - focusHeight) / 2; } function setCanvasSizing(){ backgroundCanvas.width = targetWidth; backgroundCanvas.height = targetHeight; } function updateObject(){ if(maintainScale){ obj.focusWidth = focusWidth; obj.focusHeight = focusHeight; obj.focusType = focusType; } obj.width = targetWidth; obj.height = targetHeight; obj.img = backgroundCanvas; } function cycle(){ backgroundContext.drawImage(img, offsetX + obj.movementX, offsetY + obj.movementY, focusWidth, focusHeight); } } } function createFileInput(){ var input = document.createElement('input'); input.type = 'file'; return input; } function getTextWidth(ctx, fontStyle, text){ ctx.font = fontStyle; return ctx.measureText(text).width; } function getImageURL(data){ var images = data.media.images; for(var i=0, l=images.length; i= itemAreaObj.x && eX <= itemAreaObj.x + itemAreaObj.width) && (eY >= itemAreaObj.y && eY <= itemAreaObj.y + itemAreaObj.height)) itemAreaClick(); else if((eX >= logoAreaObj.x && eX <= logoAreaObj.x + logoAreaObj.width) && (eY >= logoAreaObj.y && eY <= logoAreaObj.y + logoAreaObj.height)) logoAreaClick(); } function checkClickItems(e){ var eX = e.layerX, eY = e.layerY; for(var i=0, l=clickItems.length; i= x && eX <= x + width) && (eY >= y && eY <= y + height)) fireItem(item); } function fireItem(item){ var clickAction = item.views[viewFrame].clickItem.action; if(clickAction == 'fileSelect') { fileSelectAction(item); } } } function checkHoverItems(e){ var eX = e.layerX, eY = e.layerY, change = []; for(var i=0, l=hoverItems.length; i= x && eX <= x + width) && (eY >= y && eY <= y + height)) fireItem(item); else if (item.activeHover == true) { var __storedValue = item.__storedValue, __storedKey = item.__storedKey; delete item.__storedValue; delete item.__storedKey; item[__storedKey] = __storedValue; item.activeHover = false; change.push(item); } } if(change.length > 0) run(change, true); function fireItem(item){ var updateKey = item.views[viewFrame].hoverItem['updateKey'] || 'src'; if(!item['__storedValue']){ var __storedValue = item[updateKey]; delete item[updateKey]; item['__storedValue'] = __storedValue; item['__storedKey'] = updateKey; item[updateKey] = item.views[viewFrame].hoverItem[updateKey]; item.activeHover = true; change.push(item); } } } function fileSelectAction(obj){ fileInputCallback = cb; fileInput.click(); function cb(e){ var d = e[0]; obj.type = 'image'; obj.src = d.result; if(obj.fileSelectDeleteItems) { deleteFileSelectItems(obj.fileSelectDeleteItems); delete obj.fileSelectDeleteItems; } createCanvasImage(obj, cycle); if(obj.views[viewFrame].hoverItem) delete obj.views[viewFrame].hoverItem; } } function deleteFileSelectItems(array){ for(var i=array.length - 1; i >= 0; i--){ var item = array[i]; dataArray.splice(item, 1); } } function startDrag(e){ dragStart = [e.layerX, e.layerY]; dragState = true; dragFocus.currentMovementX = dragFocus.movementX; dragFocus.currentMovementY = dragFocus.movementY; } function endDrag(e){ dragEnd = [e.layerX, e.layerY]; dragState = false; delete dragFocus.currentMovementX; delete dragFocus.currentMovementX; } function updateDragFocus(e){ run(); function run(){ var layerX = e.layerX, layerY = e.layerY; if(dragFocus != undefined){ if(dragFocus.focusType == 'width') dragFocus.movementY = checkDragY(layerY, dragStart[1]); else if(dragFocus.focusType == 'height') dragFocus.movementX = checkDragX(layerX, dragStart[0]); dragFocus.update(); cycle(); } } } function checkDragY(layerY, startY){ var addValue = dragFocus.currentMovementY + (layerY - startY), sumValue = dragFocus.height + addValue, movementDelta = dragFocus.height - dragFocus.focusHeight; if(addValue < movementDelta) return movementDelta; else if(addValue <= 0) return addValue; else return 0; } function checkDragX(layerX, startX){ var addValue = dragFocus.currentMovementX + (layerX - startX), sumValue = dragFocus.width + addValue, movementDelta = dragFocus.width - dragFocus.focusWidth; if(addValue < movementDelta) return movementDelta; else if(addValue <= 0) return addValue; else return 0; } function exit(){ if(events) events.reset(); events = null; } }