diff --git a/js/canvas-model.js b/js/canvas-model.js index 4606bb4..6aff9ca 100644 --- a/js/canvas-model.js +++ b/js/canvas-model.js @@ -1,23 +1,23 @@ import eventPublisher from "./publisher"; // HTMLCanvasElementをラップし, canvasRenderingContext2Dに関する操作を提供する -function CanvasModel(element) { - this.element = element; - this.context = this.element.getContext("2d"); -} - -// 外からはアクセスしないでください。 -CanvasModel.prototype.getImageData = function() { - return this.context.getImageData(0, 0, - this.element.width, this.element.height); -}; - -CanvasModel.prototype.setImageData = function(imageData) { - this.context.clearRect(0, 0, - this.element.width, this.element.height); - if (imageData !== null) { - this.context.putImageData(imageData, 0, 0); +class CanvasModel { + constructor(element) { + this.element = element; + this.context = this.element.getContext("2d"); } -}; + // 外からはアクセスしないでください。 + getImageData() { + return this.context.getImageData(0, 0, + this.element.width, this.element.height); + } + setImageData(imageData) { + this.context.clearRect(0, 0, + this.element.width, this.element.height); + if (imageData !== null) { + this.context.putImageData(imageData, 0, 0); + } + } +} export default CanvasModel; diff --git a/js/drawing-configuration.js b/js/drawing-configuration.js index fbf70cf..9fb7c71 100644 --- a/js/drawing-configuration.js +++ b/js/drawing-configuration.js @@ -1,33 +1,36 @@ import eventPublisher from "./publisher"; -function DrawingConfiguration() { - this.defaultPalleteColors = []; - this.color = ""; - this.lineWidth = 0; -} +class DrawingConfiguration { + constructor() { + this.defaultPalleteColors = []; + this.color = ""; + this.lineWidth = 0; + } + + // これをコンストラクタに入れないのは、 + // ViewManager(など)で、subscribeした後に、 + // publishをしたいため。 + setDefaultValues() { + this.defaultPalleteColors = []; + eventPublisher.subscribe("defaultPalleteColors:after", + (defaultPalleteColors) => { + this.defaultPalleteColors = defaultPalleteColors; + }); + eventPublisher.publish("defaultPalleteColors", ["red", "orange", "yellow", + "lightgreen", "green", "skyblue", "blue", "purple", "black", "white"]); -// これをコンストラクタに入れないのは、 -// ViewManager(など)で、subscribeした後に、 -// publishをしたいため。 -DrawingConfiguration.prototype.setDefaultValues = function() { - this.defaultPalleteColors = []; - eventPublisher.subscribe("defaultPalleteColors:after", - (defaultPalleteColors) => { - this.defaultPalleteColors = defaultPalleteColors; - }); - eventPublisher.publish("defaultPalleteColors", ["red", "orange", "yellow", - "lightgreen", "green", "skyblue", "blue", "purple", "black", "white"]); + this.color = ""; + eventPublisher.subscribe("color:after", (color) => { + this.color = color; + }); + eventPublisher.publish("color", "red"); - this.color = ""; - eventPublisher.subscribe("color:after", (color) => { - this.color = color; - }); - eventPublisher.publish("color", "red"); + this.lineWidth = 0; + eventPublisher.subscribe("lineWidth:after", (lineWidth) => { + this.lineWidth = lineWidth; + }); + eventPublisher.publish("lineWidth", 10); + } +} - this.lineWidth = 0; - eventPublisher.subscribe("lineWidth:after", (lineWidth) => { - this.lineWidth = lineWidth; - }); - eventPublisher.publish("lineWidth", 10); -}; export default DrawingConfiguration; diff --git a/js/frame.js b/js/frame.js index 546ad08..f531252 100644 --- a/js/frame.js +++ b/js/frame.js @@ -1,5 +1,9 @@ -function Frame() { - this.imageData = null; +class Frame { + constructor() { + this.imageData = null; + } } + + export default Frame; diff --git a/js/frames-controller.js b/js/frames-controller.js index d8fd51c..5ff953d 100644 --- a/js/frames-controller.js +++ b/js/frames-controller.js @@ -3,7 +3,8 @@ import eventPublisher from "./publisher"; import CanvasModel from "./canvas-model"; // frame の追加・削除、currentFrameの切り替えをModel上で行う -function FramesController(canvas) { +class FramesController{ +constructor(canvas) { let updateImageDataToNextData; this.frames = []; this.currentFrameId = 0; @@ -19,16 +20,15 @@ function FramesController(canvas) { }; eventPublisher.subscribe("currentFrameId", updateImageDataToNextData); } - // パラメータ id : どこの後ろに追加するのか(今は実装していない) -FramesController.prototype.append = function(id) { - const frame = new Frame(); + +append(id) { + const frame = new Frame(); // 今はいいが、あとで splice に変える this.frames.push(frame); eventPublisher.publish("frames", this.frames); -}; - -FramesController.prototype.remove = function(id) { +} +remove(id) { if (this.frames.length <= 1) { throw new Error("残りフレーム数が1なので、削除することができません。"); } @@ -43,15 +43,23 @@ FramesController.prototype.remove = function(id) { eventPublisher.publish("currentFrameId", nextCurrentFrameId); }; -FramesController.prototype.setCurrentFrame = function(frameId) { +setCurrentFrame(frameId){ eventPublisher.publish("currentFrameId", frameId); -}; - -FramesController.prototype.getFrameById = function(frameId) { - return this.frames[frameId]; -}; +} + + getFrameById(frameId){ + return this.frames[frameId]; + } -FramesController.prototype.getCurrentFrame = function() { +getCurrentFrame(){ return this.frames[this.currentFrameId]; -}; +} +} + + + + + + // 今はいいが、あとで splice に変える + export default FramesController; diff --git a/js/paint-manager.js b/js/paint-manager.js index 4c2b580..35de93e 100644 --- a/js/paint-manager.js +++ b/js/paint-manager.js @@ -1,109 +1,111 @@ import eventPublisher from "./publisher"; - +let isMouseDown = false; +let previousMousePosition; // HTMLCanvasElementをラップし, canvasRenderingContext2Dに関する操作を提供する -function PaintManager(element) { - let changeDrawState; +class PaintManager{ + constructor(element) { + let changeDrawState; - this.element = element; - this.element.width = window.innerWidth; - this.element.height = window.innerHeight; + this.element = element; + this.element.width = window.innerWidth; + this.element.height = window.innerHeight; - this.element.addEventListener("mousedown", - event => { this.mouseDownCanvas(event); }); - this.element.addEventListener("mouseup", () => { this.mouseUpCanvas(); }); - this.element.addEventListener("mousemove", - event => { this.mouseMoveCanvas(event); }); + this.element.addEventListener("mousedown", + event => { this.mouseDownCanvas(event); }); + this.element.addEventListener("mouseup", () => { this.mouseUpCanvas(); }); + this.element.addEventListener("mousemove", + event => { this.mouseMoveCanvas(event); }); - this.context = this.element.getContext("2d"); - this.drawState = "idling"; - this.isLock = false; + this.context = this.element.getContext("2d"); + this.drawState = "idling"; + this.isLock = false; - changeDrawState = (drawState) => { - this.drawState = drawState; - }; - eventPublisher.subscribe("drawState", changeDrawState); + changeDrawState = (drawState) => { + this.drawState = drawState; + }; + eventPublisher.subscribe("drawState", changeDrawState); - // drawingConfiguration から、コピーしておく。 - this.color = ""; - eventPublisher.subscribe("color", (color) => { - this.color = color; - }); + // drawingConfiguration から、コピーしておく。 + this.color = ""; + eventPublisher.subscribe("color", (color) => { + this.color = color; + }); - this.lineWidth = 0; - eventPublisher.subscribe("lineWidth", (lineWidth) => { - this.lineWidth = lineWidth; - }); - - eventPublisher.subscribe("isPlaying", (isPlaying) => { - this.isLock = isPlaying; - }); -} + this.lineWidth = 0; + eventPublisher.subscribe("lineWidth", (lineWidth) => { + this.lineWidth = lineWidth; + }); -let isMouseDown = false; -let previousMousePosition; -PaintManager.prototype.mouseDownCanvas = function(event) { - if (!this.isLock) { - isMouseDown = true; - previousMousePosition = { x: event.clientX, y: event.clientY }; - eventPublisher.publish("drawState", "drawing"); + eventPublisher.subscribe("isPlaying", (isPlaying) => { + this.isLock = isPlaying; + }); + } + + mouseDownCanvas(event) { + if (!this.isLock) { + isMouseDown = true; + previousMousePosition = { x: event.clientX, y: event.clientY }; + eventPublisher.publish("drawState", "drawing"); + } } -}; -PaintManager.prototype.mouseUpCanvas = function() { - if (!this.isLock) { - isMouseDown = false; - eventPublisher.publish("drawState", "idling"); + + mouseUpCanvas(){ + if (!this.isLock) { + isMouseDown = false; + eventPublisher.publish("drawState", "idling"); + } } -}; -PaintManager.prototype.mouseMoveCanvas = function(event) { - if (!this.isLock) { - if (isMouseDown) { - if (this.color === "white") { - this.eraseByLine( - previousMousePosition, - { x: event.clientX, y: event.clientY }, - this.lineWidth - ); - } else { - this.drawLine( - previousMousePosition, - { x: event.clientX, y: event.clientY }, - this.color, - this.lineWidth - ); + mouseMoveCanvas(event) { + if (!this.isLock) { + if (isMouseDown) { + if (this.color === "white") { + this.eraseByLine( + previousMousePosition, + { x: event.clientX, y: event.clientY }, + this.lineWidth + ); + } else { + this.drawLine( + previousMousePosition, + { x: event.clientX, y: event.clientY }, + this.color, + this.lineWidth + ); + } + previousMousePosition = { x: event.clientX, y: event.clientY }; } - previousMousePosition = { x: event.clientX, y: event.clientY }; } } -}; -/** - * 線を描きます。 - */ -PaintManager.prototype.drawLine = function( + /** + * 線を描きます。 + */ + drawLine( startPosition, - endPosition, - strokeColor, - lineWidth) { + endPosition, + strokeColor, + lineWidth) { - this.context.strokeStyle = strokeColor; - this.context.lineWidth = lineWidth; - this.context.beginPath(); - this.context.moveTo(startPosition.x, startPosition.y); - this.context.lineTo(endPosition.x, endPosition.y); - this.context.lineCap = "round"; - this.context.stroke(); -}; + this.context.strokeStyle = strokeColor; + this.context.lineWidth = lineWidth; + this.context.beginPath(); + this.context.moveTo(startPosition.x, startPosition.y); + this.context.lineTo(endPosition.x, endPosition.y); + this.context.lineCap = "round"; + this.context.stroke(); + } -/** - * 線で消します。消した部分は透明になります。 - */ -PaintManager.prototype.eraseByLine = function( - startPosition, - endPosition, - lineWidth) { - this.context.globalCompositeOperation = "destination-out"; - this.drawLine(startPosition, endPosition, "#000", lineWidth); - this.context.globalCompositeOperation = "source-over"; -}; + /** + * 線で消します。消した部分は透明になります。 + */ + eraseByLine( + startPosition, + endPosition, + lineWidth) { + this.context.globalCompositeOperation = "destination-out"; + this.drawLine(startPosition, endPosition, "#000", lineWidth); + this.context.globalCompositeOperation = "source-over"; + } +} export default PaintManager; diff --git a/js/player.js b/js/player.js index 98a78a2..154b4a1 100644 --- a/js/player.js +++ b/js/player.js @@ -8,8 +8,9 @@ const playInterval = 250; * 再生された時に、Frameを切り替える処理もここで行う。 * 再生された時に他に必要な処理(Menuを隠すなど)は、各自クラスでsubscribeして行う。 */ -function Player(framesController) { - this.isPlaying = false; +class Player{ + constructor(framesController){ + this.isPlaying = false; this.playInterval = playInterval; this.framesController = framesController; this.changeFrameId = -1; @@ -21,9 +22,10 @@ function Player(framesController) { clearTimeout(this.changeFrameId); } }); -} + } -Player.prototype.changeFrame = function(currentFrameId) { + +changeFrame(currentFrameId) { let nextCurrentFrameId; this.framesController.setCurrentFrame(currentFrameId); if (currentFrameId >= this.framesController.frames.length - 1) { @@ -34,6 +36,6 @@ Player.prototype.changeFrame = function(currentFrameId) { this.changeFrameId = setTimeout(() => { this.changeFrame(nextCurrentFrameId); }, this.playInterval); -}; - +} +} export default Player; diff --git a/js/publisher.js b/js/publisher.js index a0aa6d9..c434d5b 100644 --- a/js/publisher.js +++ b/js/publisher.js @@ -1,16 +1,17 @@ // Publisherは、データを保存せず、外部へ変更を知らせる機能に絞る。 -function Publisher() { - this.observers = {}; -} +class Publisher{ + constructor(){ + this.observers = {}; + } -Publisher.prototype.subscribe = function(type, observer) { - if (typeof this.observers[type] === "undefined") { +subscribe(){ + if (typeof this.observers[type] === "undefined") { this.observers[type] = []; } this.observers[type].push(observer); -}; +} -Publisher.prototype.publish = function(type, nextData) { +publish(){ if (type.indexOf(":") !== -1) { throw new Error("publishのtypeに「:」を含むことはできません。"); } @@ -25,7 +26,8 @@ Publisher.prototype.publish = function(type, nextData) { observer(nextData); }); } -}; +} +} export default new Publisher(); diff --git a/js/view-manager.js b/js/view-manager.js index e12da83..e5f0219 100644 --- a/js/view-manager.js +++ b/js/view-manager.js @@ -5,8 +5,9 @@ import SequenceView from "./view/sequence-view"; import PlayerView from "./view/player-view"; import eventPublisher from "./publisher"; -function ViewManager(framesController) { - this.colorPicker = +class ViewManager{ + constructor(framesController){ + this.colorPicker = new ColorPickerView(document.getElementById("menu-colors")); eventPublisher.subscribe("defaultPalleteColors", (colors) => { this.colorPicker.clearPalette(); @@ -23,6 +24,6 @@ function ViewManager(framesController) { this.player = new PlayerView(document.getElementById("play-btn")); this.menu = new MenuView(); + } } - export default ViewManager; diff --git a/js/view/color-picker-view.js b/js/view/color-picker-view.js index 901d407..3fb6be6 100644 --- a/js/view/color-picker-view.js +++ b/js/view/color-picker-view.js @@ -1,8 +1,8 @@ import eventPublisher from "./../publisher"; -function ColorPickerView(elem) { - // このelem には、ul要素が入ってくる(はず)。 - this.element = elem; +class colorpickerview{ + constructor(elem){ + this.element = elem; eventPublisher.subscribe("color", (color) => { let selectedPalette = this.element.querySelector(".selected-palette"); let nextPalette; @@ -14,9 +14,9 @@ function ColorPickerView(elem) { nextPalette.classList.add("selected-palette"); } }); -} + } -ColorPickerView.prototype.addPalette = function(color) { +addPalette(color)){ let palette; if (!isColor(color)) { @@ -31,17 +31,20 @@ ColorPickerView.prototype.addPalette = function(color) { palette.addEventListener("click", event => { eventPublisher.publish("color", event.target.style.backgroundColor); }); -}; - -ColorPickerView.prototype.clearPalette = function() { +} +clearPalette(){ this.element.innerHTML = ""; }; +} -function isColor(color) { - const testElement = document.createElement("span"); +class isColor{ + constructor(color){ + const testElement = document.createElement("span"); testElement.style.backgroundColor = color; return testElement.style.backgroundColor !== ""; -} + } + } + export default ColorPickerView; diff --git a/js/view/line-width-picker-view.js b/js/view/line-width-picker-view.js index 339374f..2f8c5e3 100644 --- a/js/view/line-width-picker-view.js +++ b/js/view/line-width-picker-view.js @@ -1,22 +1,23 @@ import eventPublisher from "./../publisher"; -function LineWidthPickerPanel(elem) { - // このelem には、input[type="range"] 要素が入ってくる(はず)。 - this.element = elem; +class LineWidthPickerPanel { + constructor(elem){ + this.element = elem; eventPublisher.subscribe("lineWidth", (lineWidth) => { this.element.value = lineWidth; }); this.element.addEventListener("change", event => { eventPublisher.publish("lineWidth", event.target.value); }); -} + } -LineWidthPickerPanel.prototype.changeMaxLineWidth = function(maxLineWidth) { - // TODO -}; +changeMaxLineWidth(maxLineWidth){ -LineWidthPickerPanel.prototype.changeMinLineWidth = function(minLineWidth) { // TODO }; +changeMinLineWidth(minLineWidth){ + // TODO +} +} export default LineWidthPickerPanel; diff --git a/js/view/menu-view.js b/js/view/menu-view.js index f6f6ce6..6b0d07c 100644 --- a/js/view/menu-view.js +++ b/js/view/menu-view.js @@ -1,7 +1,8 @@ import eventPublisher from "./../publisher"; -function MenuView() { - this.isOpen = false; +class MenuView{ + constructor(){ + this.isOpen = false; this.isPlaying = false; this.setCollapsibleButtonMode(false); eventPublisher.subscribe("drawState", (newState) => { @@ -25,9 +26,9 @@ function MenuView() { this.setMenuVisible(!this.isOpen); } }); -} + } -MenuView.prototype.setMenuVisible = function(isOpen) { +setMenuVisible(isOpen){ const menu = document.getElementById("menu"); const direction = isOpen ? "alternate" : "alternate-reverse"; this.isOpen = isOpen; @@ -35,18 +36,18 @@ MenuView.prototype.setMenuVisible = function(isOpen) { [{ transform: "translate(-20vw)" }, { transform: "translate(0px)" }], { direction: direction, duration: 250, fill: "both", easing: "ease-in-out" }); -}; - +} // collapsibleButton : メニューの右側にあるボタン -MenuView.prototype.setCollapsibleButtonVisible = function(visible) { + +setCollapsibleButtonVisible(visible){ const collapsibleButton = document.getElementById("menu-collapsible-btn"); const direction = visible ? "alternate" : "alternate-reverse"; collapsibleButton.animate( [{ transform: "translate(-30px)" }, { transform: "translate(0px)" }], { direction: direction, duration: 100, fill: "both" }); -}; +} -MenuView.prototype.setCollapsibleButtonMode = function(isPlaying) { +setCollapsibleButtonMode(isPlaying){ this.isPlaying = isPlaying; const icon = document.querySelector("#menu-collapsible-btn i"); if (isPlaying) { @@ -56,5 +57,6 @@ MenuView.prototype.setCollapsibleButtonMode = function(isPlaying) { icon.classList.add("fa-cog"); icon.classList.remove("fa-pause"); } -}; +} +} export default MenuView; diff --git a/js/view/player-view.js b/js/view/player-view.js index 9c26a99..ad11fb5 100644 --- a/js/view/player-view.js +++ b/js/view/player-view.js @@ -1,10 +1,12 @@ import eventPublisher from "./../publisher"; -function PlayerView(element) { - this.element = element; +class PlayerView{ + constructor(){ + this.element = element; this.element.addEventListener("click", () => { eventPublisher.publish("isPlaying", true); - }); + }); + } } export default PlayerView; diff --git a/js/view/sequence-view.js b/js/view/sequence-view.js index 7a441cb..151525a 100644 --- a/js/view/sequence-view.js +++ b/js/view/sequence-view.js @@ -1,7 +1,8 @@ import eventPublisher from "./../publisher"; -function SequencePanel(elem, framesController) { - this.elem = elem; +class SequencePanel{ + constructor(elem, framesController){ + this.elem = elem; this.maxFrameId = 0; this.currentFrameId = 0; this.framesController = framesController; @@ -21,6 +22,7 @@ function SequencePanel(elem, framesController) { document.getElementById("sequence-add-btn").addEventListener("click", () => { this.framesController.append(++this.maxFrameId); }); + } } /* フレームの構造 @@ -37,71 +39,66 @@ function SequencePanel(elem, framesController) { */ -function getFrameTemplate( - frameId, +class getFrameTemplate{ + constructor(frameId, mousedownFrameCallback, - mousedownRemoveCallback) { - let frame = document.createElement("div"); - let frameDeleteBtn = document.createElement("button"); - let frameUpBtn = document.createElement("button"); - let frameDownBtn = document.createElement("button"); - frame.dataset.frameIndex = frameId; - frame.classList.add("thumbnail"); - frame.addEventListener("mousedown", mousedownFrameCallback); - frameDeleteBtn.classList.add("frame-delete"); - frameUpBtn.classList.add("frame-up"); - frameDownBtn.classList.add("frame-down"); - frameDeleteBtn.innerHTML = ""; - frameDeleteBtn.addEventListener("mousedown", mousedownRemoveCallback); - frameUpBtn.innerHTML = ""; - frameDownBtn.innerHTML = ""; - frame.appendChild(frameDeleteBtn); - frame.appendChild(frameUpBtn); - frame.appendChild(frameDownBtn); - - return frame; -} + mousedownRemoveCallback){ + let frame = document.createElement("div"); + let frameDeleteBtn = document.createElement("button"); + let frameUpBtn = document.createElement("button"); + let frameDownBtn = document.createElement("button"); + frame.dataset.frameIndex = frameId; + frame.classList.add("thumbnail"); + frame.addEventListener("mousedown", mousedownFrameCallback); + frameDeleteBtn.classList.add("frame-delete"); + frameUpBtn.classList.add("frame-up"); + frameDownBtn.classList.add("frame-down"); + frameDeleteBtn.innerHTML = ""; + frameDeleteBtn.addEventListener("mousedown", mousedownRemoveCallback); + frameUpBtn.innerHTML = ""; + frameDownBtn.innerHTML = ""; + frame.appendChild(frameDeleteBtn); + frame.appendChild(frameUpBtn); + frame.appendChild(frameDownBtn); -SequencePanel.prototype.append = function(frameId) { - let newFrame = getFrameTemplate(frameId, (event) => { - // 子要素のmousedownによる発生を防ぐ - if (event.target.classList.contains("thumbnail")) { - eventPublisher.publish("currentFrameId", frameId); - this.setCurrentFrame(newFrame); - } - }, () => { - // フレーム数が1つの時は、エラーになるため削除しない。 - if (this.maxFrameId > 0) { - this.framesController.remove(frameId); + return frame; + } + append(frameId){ + let newFrame = getFrameTemplate(frameId, (event) => { + // 子要素のmousedownによる発生を防ぐ + if (event.target.classList.contains("thumbnail")) { + eventPublisher.publish("currentFrameId", frameId); + this.setCurrentFrame(newFrame); + } + }, () => { + // フレーム数が1つの時は、エラーになるため削除しない。 + if (this.maxFrameId > 0) { + this.framesController.remove(frameId); + } + }); + this.elem.appendChild(newFrame); + } + clear(){ + this.elem.innerHTML = ""; + } + remove(frame){ } - }); - this.elem.appendChild(newFrame); -}; - -SequencePanel.prototype.clear = function() { - this.elem.innerHTML = ""; -}; - -SequencePanel.prototype.remove = function(frame) { -}; - -SequencePanel.prototype.moveUp = function() { - // TODO -}; - -SequencePanel.prototype.moveDown = function() { - // TODO -}; - -SequencePanel.prototype.setCurrentFrame = function(frameIndex) { - let frame = this.elem.querySelector(`[data-frame-index="${frameIndex}"]`); - if (frame !== null) { - const selectedFrame = this.elem.querySelector(".thumbnail-selected"); - if (selectedFrame) { - selectedFrame.classList.remove("thumbnail-selected"); + moveUp(){ + // TODO + } + moveDown(){ + // TODO + } + setCurrentFrame(){ + let frame = this.elem.querySelector(`[data-frame-index="${frameIndex}"]`); + if (frame !== null) { + const selectedFrame = this.elem.querySelector(".thumbnail-selected"); + if (selectedFrame) { + selectedFrame.classList.remove("thumbnail-selected"); + } + frame.classList.add("thumbnail-selected"); } - frame.classList.add("thumbnail-selected"); } -}; +} export default SequencePanel;