表示調整
閉じる
挿絵表示切替ボタン
▼配色
▼行間
▼文字サイズ
▼メニューバー
×閉じる

ブックマークに追加しました

設定
0/400
設定を保存しました
エラーが発生しました
※文字以内
ブックマークを解除しました。

エラーが発生しました。

エラーの原因がわからない場合はヘルプセンターをご確認ください。

ブックマーク機能を使うにはログインしてください。
とある割烹芸人の開発日誌 ~100日以内に割烹エディターをリリースする割烹芸人~  作者: とある割烹芸人まーくつーせかんど
正式版への道
33/48

93日目 割烹芸人の実装9

最後にLINE割烹を作っていきます。

さて、最後にLINE風割烹を作っていきます。


とりあえずまずはLINE風のブロックを作れるように割烹エディターに追加していきます。



class ChatStyle


を作って、 constructor、render、renderSettings、save、sanitize、toolboxなどを設定していきましてっと。


class ChatStyle{


static get enableLineBreaks(){

return true;

}


constructor({data, config, api}){


this.api=api;

this.config = config || {};


this.data = {

text: data.text || '',

fontSize : data.fontSize !== undefined ? data.fontSize : '1',

color: data.color !== undefined ? data.color : '#333333',

backcolor: data.backcolor !== undefined ? data.backcolor : '#B1ED8B',

position:data.position !== undefined ? data.position : 'rightside',

imgurl:data.imgurl !== undefined ? data.imgurl : ''

};



this._element = this.drawView();


this._changePosition(this.data.position);


const headerbox = this._element.querySelector('.chat-text');

const chatallow = this._element.querySelector('.chat-allow');


headerbox.innerHTML = this.data.text;

headerbox.style.color=this.data.color;

headerbox.style.background=this.data.backcolor;

chatallow .style.borderLeftColor=this.data.backcolor;

chatallow .style.borderRightColor=this.data.backcolor;

headerbox.style.fontSize=this.data.fontSize+ 'em';


this.settings = [

{

name:'leftside',

icon:'左向'

},

{

name:'rightside',

icon:'右向'

},

{

name: 'color',

icon:'装飾',

},

{

name:'copy',

icon:'複製'

}

]

}


onKeyDOWN(e){

if( e.key === 'Enter' && !e.shiftKey ){


e.stopPropagation();

e.preventDefault();


let selection = window.getSelection(),

range = selection.getRangeAt(0),

newline = document.createTextNode('\u200B'),//零幅スペース

br = document.createElement('br');


range.deleteContents();

range.insertNode(newline);


range.insertNode(br);


range.setStartAfter(br);

range.setEndAfter(br);


range.collapse(false);


selection.removeAllRanges();

selection.addRange(range);


}

}


drawView() {

const containr = document.createElement('div');

const textblock = document.createElement('div');

const imgblock = document.createElement('div');

const allowblock = document.createElement('div');

const setblock = document.createElement('form');


textblock.classList.add('chat-text');

allowblock.classList.add('chat-allow');

imgblock.classList.add('chat-img');


containr.classList.add('custom-chat');


textblock.contentEditable = true;


textblock.addEventListener('keydown', this.onKeyDOWN);


containr.appendChild(imgblock);

containr.appendChild(allowblock);

containr.appendChild(textblock);

containr.appendChild(setblock);


return containr;

}


render(){

return this._element;

}


renderSettings(){


const wrapper = document.createElement('div');


this.settings.forEach(tune =>{

let button = document.createElement('div');


button.classList.add(this.api.styles.settingsButton);


button.innerHTML = tune.icon;

wrapper.appendChild(button);


if(tune.name === 'leftside' || tune.name === 'rightside'){

button.classList.toggle(this.api.styles.settingsButtonActive, tune.name === this.data.position);

}else if(tune.name === 'copy'){


}else{

if(this._setform){

button.classList.toggle(this.api.styles.settingsButtonActive);

}

}


button.addEventListener('click', ()=>{

if(tune.name === 'leftside' || tune.name === 'rightside'){


wrapper.querySelectorAll(`.${this.api.styles.settingsButton}`).forEach(el => {

if((el.innerHTML === '左向' || el.innerHTML === '右向') ){

el.classList.remove(this.api.styles.settingsButtonActive);

}

});


button.classList.add(this.api.styles.settingsButtonActive);


this._changePosition(tune.name);


}else if(tune.name === 'color'){


button.classList.toggle(this.api.styles.settingsButtonActive);

if(button.classList.contains(this.api.styles.settingsButtonActive)){

this._showColorPicker();

this._setform=true;

}else{

this._hideColorPicker();

this._setform=false;

}


}else if(tune.name==='copy'){

this._copyblock();


}

});


});


return wrapper;


}


save(toolsContent){


const textbox = this._element.querySelector('.chat-text');


return {

text:textbox.innerHTML,

position:this.data.position,

fontSize:this.data.fontSize,

color:this.data.color,

backcolor:this.data.backcolor,

imgurl:this.data.imgurl

}

}


_changePosition(tune){

this.data.position=tune;

this._element.classList.remove('rightside');

this._element.classList.remove('leftside');


this._element.classList.add(tune);

}


_showColorPicker(){

const setbox = this._element.querySelector('form');


const fontsize = document.createElement('input');

const textcolor = document.createElement('input');

const backcolor = document.createElement('input');


fontsize.type = 'number';

fontsize.step = '0.1';

fontsize.min= "0.1" ;

fontsize.max= "10";

fontsize.value = this.data.fontSize;


textcolor.type = 'color';

textcolor.value = this.data.color;


backcolor.type = 'color';

backcolor.value = this.data.backcolor;


setbox.insertAdjacentHTML('beforeend', '文字色:');

setbox.appendChild(textcolor);

setbox.insertAdjacentHTML('beforeend', '

背景色:');

setbox.appendChild(backcolor);

setbox.insertAdjacentHTML('beforeend', '

文字サイズ(em):');

setbox.appendChild(fontsize);


fontsize.onchange = () => {

const headerbox = this._element.querySelector('.chat-text');


this.data.fontSize=fontsize.value;

headerbox.style.fontSize=this.data.fontSize + 'em';

};


textcolor.onchange = () => {

const headerbox = this._element.querySelector('.chat-text');


this.data.color = textcolor.value;

headerbox.style.color=this.data.color;

};


backcolor.onchange = () => {

const headerbox = this._element.querySelector('.chat-text');

const chatallow = this._element.querySelector('.chat-allow');

this.data.backcolor = backcolor.value;

headerbox.style.background=this.data.backcolor;

chatallow .style.borderLeftColor=this.data.backcolor;

chatallow .style.borderRightColor=this.data.backcolor;

};


}


_hideColorPicker(){

const setbox = this._element.querySelector('form');


setbox.innerHTML='';

}


_copyblock(){

const headerbox = this._element.querySelector('.chat-text');


this.api.blocks.insert('chat',{text:headerbox.innerHTML,

width:this.data.width,

fontSize:this.data.fontSize,

position:this.data.position,

color:this.data.color,

bordercolor:this.data.bordercolor,

backcolor:this.data.backcolor,

url:this.data.url},{},this.api.blocks.getBlocksCount());

}


static get sanitize() {

return {

text: {

br: true,

span:{

style:true

},

}

};

}


validate(blockData) {

return blockData.text.trim() !== '';

}


static get toolbox(){

return {

icon:'吹出',

title:'吹出を挿入'

};

}

}



これでLINE風の吹き出しが出せるようになりました。


挿絵(By みてみん)


画像も入れられるようにしたかったですが、ちょっと時間が足りなさそうなので今後の課題ということで。





さて、次にデフォルトの背景を変えられるようにもしています。これはLINE風割烹限定にしておきます。



背景色を選べるようにして、変わった時に背景を変えるようにしておきます。


デフォルトはLINE風にしておきます。


挿絵(By みてみん)



さて、これでLINE割烹も完了ですね。



予定していたものはこれで大体できました。あとは取説を作っていったん完成させます。


PC版割烹の最強最大の敵、P ex先輩。


挿絵(By みてみん)


HTML5ではpタグの中にはフローコンテンツ(divとかtableとか)は入れられないようになっているが、もし入れた場合はその前の行でpタグがとじれられる。


それによってデフォルトのcssを外してしまうp ex先輩に苦しめられる割烹芸人は多い……。


まじ勘弁してください……。



詳細はこちら

【一覧表あり】HTML5でのタグの入れ子のルールを徹底まとめ

https://webliker.info/46840/

評価をするにはログインしてください。
ブックマークに追加
ブックマーク機能を使うにはログインしてください。
― 新着の感想 ―
このエピソードに感想はまだ書かれていません。
感想一覧
+注意+

特に記載なき場合、掲載されている作品はすべてフィクションであり実在の人物・団体等とは一切関係ありません。
特に記載なき場合、掲載されている作品の著作権は作者にあります(一部作品除く)。
作者以外の方による作品の引用を超える無断転載は禁止しており、行った場合、著作権法の違反となります。

この作品はリンクフリーです。ご自由にリンク(紹介)してください。
この作品はスマートフォン対応です。スマートフォンかパソコンかを自動で判別し、適切なページを表示します。

↑ページトップへ