// Handwriting plugin ;(function($) { $.fn.handwriting = function(options) { var settings = { brushColor: "rgba(0, 0, 0, 0.25)" }; settings = $.extend(settings, options || {}); return new handwritingClass(this, settings); }; var handwritingClass = function($element, settings) { this.$canvas = $element; this.moveFlag = false; this.upof = {}; // this.radius = 0; // this.lineMax = 40; // this.lineMin = 5; // this.linePressure = 3; // this.smoothness = 200; this.radius = 0; this.lineMax = 40; this.lineMin = 10; this.linePressure = 5; this.smoothness = 200; this.undoList = []; this.stepList = []; this.stepListener = settings.stepListener; this.canvas = this.$canvas[0]; this.context2d = this.canvas.getContext("2d"); this.context2d.fillStyle = settings.brushColor; var source = this; this.canvas.addEventListener('mousedown', function(event) { downEvent(source, event) }); this.canvas.addEventListener('mousemove', function(event) { moveEvent(source, event) }); this.canvas.addEventListener('mouseup', function(event) { upEvent(source, event) }); this.canvas.addEventListener('mouseout', function(event) { upEvent(source, event) }); function downEvent(source, event) { source.moveFlag = true; source.has = []; source.upof = getXY(source, event); source.stepList = []; } function upEvent(source, event) { if (source.moveFlag) { source.undoList.push(source.stepList); if (source.stepListener != null) { source.stepListener(source, source.undoList.length); } } source.moveFlag = false; } function moveEvent(source, event) { if (!source.moveFlag) return; var xy = getXY(source, event); var up = source.upof; var ur = source.radius; source.has.unshift({ time: new Date().getTime(), dis: distance(up, xy) }); var dis = 0; var time = 0; for (var n = 0; n < source.has.length - 1; n++) { dis += source.has[n].dis; time += source.has[n].time - source.has[n + 1].time; if (dis > source.smoothness) break; } var or = Math.min(time / dis * source.linePressure + source.lineMin, source.lineMax) / 2; source.radius = or; source.upof = xy; if (source.has.length <= 4) return; var len = Math.round(source.has[0].dis / 2) + 1; var context2d = source.context2d; var pathList = []; for (var i = 0; i < len; i++) { var x = up.x + (xy.x - up.x) / len * i; var y = up.y + (xy.y - up.y) / len * i; var r = ur + (or - ur) / len * i; context2d.beginPath(); context2d.arc(x, y, r, 0, 2 * Math.PI, true); context2d.fill(); pathList[i] = { "x": x, "y": y, "r": r }; } source.stepList.push(pathList); } function getXY(source, event) { var $offset = source.$canvas.offset(); return { x: event.clientX - $offset.left + (document.body.scrollLeft || document.documentElement.scrollLeft), y: event.clientY - $offset.top + (document.body.scrollTop || document.documentElement.scrollTop) } } function distance(a, b) { var x = b.x - a.x, y = b.y - a.y; return Math.sqrt(x * x + y * y); } }; handwritingClass.prototype = { toDataURL: function() { return this.canvas.toDataURL("image/png"); }, clear: function() { this.context2d.clearRect(0, 0, this.canvas.width, this.canvas.height); this.undoList = []; this.stepList = []; }, undo: function() { this.context2d.clearRect(0, 0, this.canvas.width, this.canvas.height); this.undoList.splice(this.undoList.length - 1, 1); for (var undoNum = 0; undoNum < this.undoList.length; undoNum++) { var undoStep = this.undoList[undoNum]; for (var stepNum = 0; stepNum < undoStep.length; stepNum++) { var stepPath = undoStep[stepNum]; for (var pathNum = 0; pathNum < stepPath.length; pathNum++) { var path = stepPath[pathNum]; this.context2d.beginPath(); this.context2d.arc(path.x, path.y, path.r, 0, 2 * Math.PI, true); this.context2d.fill(); } } } } }; })(jQuery); // Greeting card plugin ;(function($) { $.fn.greetingCard = function(options) { return new greetingCardClass(this); }; var greetingCardClass = function($element, settings) { this.$canvas = $element; this.canvas = this.$canvas[0]; this.context2d = this.canvas.getContext("2d"); }; greetingCardClass.prototype = { toDataURL: function() { return this.canvas.toDataURL("image/png"); }, toDownloadURL: function() { return this.canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"); }, merge: function(dataURL, cardId, dx, dy, dwidth, dheight, callback) { var self = this; var mergeContext2d = this.context2d; mergeContext2d.clearRect(0, 0, this.canvas.width, this.canvas.height); var cardImage = document.getElementById(cardId); cardImage.crossOrigin = "Anonymous"; mergeContext2d.drawImage(cardImage, 0, 0); var writeImage = new Image(); writeImage.crossOrigin = "Anonymous"; writeImage.src = dataURL; writeImage.onload = function() { var sx = sy = 0; var swidth = writeImage.width; var sheight = writeImage.height; mergeContext2d.drawImage(writeImage, sx, sy, swidth, sheight, dx, dy, dwidth, dheight); if (callback != undefined) callback(self.toDataURL()); } } }; })(jQuery); // Preview card plugin ; (function($) { $.fn.previewCard = function(options) { return new previewCardClass(this); }; var previewCardClass = function($element, settings) { this.canvas = document.createElement('canvas'); this.canvas.width = 610; this.canvas.height = 394; this.context2d = this.canvas.getContext("2d"); this.desc = $element.data("desc"); this.cardImage = $element[0]; this.originImage = new Image(); this.originImage.src = $element.data("src"); }; previewCardClass.prototype = { mergeTo: function(dataURL) { var self = this; var cardDesc = this.desc; this.context2d.drawImage(this.originImage, 0, 0); var writeImage = new Image(); writeImage.src = dataURL; writeImage.onload = function() { var sx = sy = 0; var swidth = writeImage.width; var sheight = writeImage.height; self.context2d.drawImage(writeImage, sx, sy, swidth, sheight, self.desc.dx, self.desc.dy, self.desc.dw, self.desc.dh); var mergeDataURL = self.canvas.toDataURL("image/png"); self.cardImage.src = mergeDataURL; }; } }; })(jQuery); $(function() { var THIRD_STEP_ACTION = 1; var UNDO_ACTION = 2; var CLEAR_ACTION = 3; var FINISH_ACTION = 4; var SEND_ACTION = 5; var $handwriting = $("#writeCanvas").handwriting({ stepListener: function(source, step) { if (step == 3) { sendGreetingCardLog(THIRD_STEP_ACTION); } } }); var $greetingCard = $("#greetingCardCanvas").greetingCard(); var newYearCard1 = $("#new-year-card-1").previewCard(); var newYearCard2 = $("#new-year-card-2").previewCard(); var newYearCard3 = $("#new-year-card-3").previewCard(); var newYearCard4 = $("#new-year-card-4").previewCard(); var $cardForm = $("#card_form"); var $toNameResult = $("#to_name_result"); var $toEmailResult = $("#to_email_result"); var $thanksArea = $("#thanksArea"); var $successMessage = $("#successMessage"); var $sendingMessage = $("#sendingMessage"); var $sendToButton = $("#sendToButton"); var $sendArea = $("#sendArea"); $(".cardList").each(function(index, element) { $(element).on("click", function() { $("#greetingCardPreview").fadeIn(); var desc = $("img", this).data("desc"); $greetingCard.merge( $handwriting.toDataURL(), desc.cardId, desc.dx, desc.dy, desc.dw, desc.dh); var base64 = $greetingCard.toDataURL(); $("#image_data").attr("value", base64); }); }); $("#finishButton").click(function() { sendGreetingCardLog(FINISH_ACTION); var $cardSelect = $("#cardSelect"); $cardSelect.fadeIn(); var scrollTo = $cardSelect.offset().top - $cardSelect.height(); $("body").animate({ scrollTop: scrollTo }); newYearCard1.mergeTo($handwriting.toDataURL()); newYearCard2.mergeTo($handwriting.toDataURL()); newYearCard3.mergeTo($handwriting.toDataURL()); newYearCard4.mergeTo($handwriting.toDataURL()); }); $("#saveCardButton").click(function() { var saveLink = document.createElement("a"); saveLink.href = $greetingCard.toDownloadURL(); saveLink.download = "chinese-new-year-" + (new Date()).getTime() + ".png"; var clickEvent = document.createEvent("MouseEvents"); clickEvent.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); saveLink.dispatchEvent(clickEvent); }); $("#clearButton").click(function() { sendGreetingCardLog(CLEAR_ACTION); $handwriting.clear(); }); $("#undoButton").click(function() { sendGreetingCardLog(UNDO_ACTION); $handwriting.undo(); }); $("#closeButton").click(function() { $("#greetingCardPreview").fadeOut(); $thanksArea.fadeOut(); $sendToButton.addClass("sending"); $sendArea.attr("data-status", "display"); $sendArea.fadeIn(); }); $sendToButton.click(function() { var areaStatus = $sendArea.attr("data-status"); $thanksArea.hide(); if (areaStatus == "hidden") { $sendToButton.addClass("sending"); $sendArea.attr("data-status", "display"); $sendArea.fadeIn(); } else { $sendArea.attr("data-status", "hidden"); $sendArea.fadeOut(); $sendToButton.removeClass("sending"); } }); $cardForm.submit(function() { $sendToButton.removeClass("sending"); $sendArea.attr("data-status", "hidden"); $sendArea.hide(); $successMessage.hide(); $sendingMessage.show(); $thanksArea.fadeIn(); $.ajax({ type: "POST", url: "/guide-use.php/travelguide/sendGreetingCardByAjax/", dataType: "json", data: $cardForm.serializeArray(), success: function(result) { if (result.hasError) { $sendingMessage.text(result.errorMessage); console.info(result.detailMessage); return false; } else { $successMessage.show(); $sendingMessage.hide(); $toNameResult.text(result.data.M_ToName); $toEmailResult.text(result.data.M_ToEmail); return true; } }, error: function(err) { console.info(err); return false; } }); return false; }); function sendGreetingCardLog(action) { $.ajax({ type: "POST", url: "/guide-use.php/travelguide/logGreetingCard/", dataType: "json", data: {log_action: action}, success: function(result) { }, error: function(err) { return false; } }); } });