UNPKG

nadesiko3

Version:
483 lines (480 loc) 18.8 kB
/* eslint-disable quote-props */ const errMsgCanvasInit = '描画を行うためには、HTML内にcanvasを配置し、idを振って『描画開始』命令に指定します。' export default { // @描画 '描画開始': { // @描画先にCanvas(文字列でクエリの指定も可)を指定して描画API(2D)の利用準備する // @びょうがかいし type: 'func', josi: [['の', 'へ', 'で']], pure: true, fn: function (cv: any, sys: any) { if (typeof cv === 'string') { cv = document.querySelector(cv) || document.getElementById(cv) } if (!cv) { throw new Error('『描画開始』でCanvasを取得できませんでした。') } sys.__addPropMethod(cv) sys.__canvas = cv sys.__ctx = cv.getContext('2d') sys.__fillStyle = 'black' sys.__strokeStyle = 'black' sys.__setSysVar('描画中キャンバス', cv) sys.__setSysVar('描画中コンテキスト', sys.__ctx) }, return_none: true }, '描画中キャンバス': { type: 'const', value: null }, // @ びょうがちゅうきゃんばす '描画中コンテキスト': { type: 'const', value: null }, // @ びょうがちゅうこんてきすと 'キャンバス状態保存': { // @Canvasの状態を保存(save) // @ きゃんばすじょうたいほぞん type: 'func', josi: [], pure: true, fn: function (sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.save() }, return_none: true }, 'キャンバス状態復元': { // @Canvasの状態を復元(restore) // @ きゃんばすじょうたいふくげん type: 'func', josi: [], pure: true, fn: function (sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.restore() }, return_none: true }, '線色設定': { // @Canvasの線の描画色(lineStyle)を指定する // @ せんいろしてい type: 'func', josi: [['に', 'へ']], pure: true, fn: function (v: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__strokeStyle = v if (v !== '') { sys.__ctx.strokeStyle = v } }, return_none: true }, '塗色設定': { // @Canvasへの描画色(fillStyle)を指定する // @ ぬりいろしてい type: 'func', josi: [['に', 'へ']], pure: true, fn: function (v: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__fillStyle = v if (v !== '') { sys.__ctx.fillStyle = v } }, return_none: true }, '線描画': { // @ [x1, y1]から[x2, y2]まで線を描画する // @ せんびょうが type: 'func', josi: [['から'], ['へ', 'まで']], pure: true, fn: function (a: any, b: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.beginPath() sys.__ctx.moveTo(a[0], a[1]) sys.__ctx.lineTo(b[0], b[1]) sys.__ctx.stroke() }, return_none: true }, '線太設定': { // @ vに線の太さ設定 // @ せんふとさせってい type: 'func', josi: [['に', 'へ']], pure: true, fn: function (v: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.lineWidth = v }, return_none: true }, '四角描画': { // @ [x, y, w, h]で矩形を描画する // @ しかくびょうが type: 'func', josi: [['の', 'へ', 'に']], pure: true, fn: function (b: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } if (sys.__fillStyle === '' && sys.__strokeStyle === '') { return } sys.__ctx.beginPath() sys.__ctx.rect(b[0], b[1], b[2], b[3]) if (sys.__fillStyle !== '') { sys.__ctx.fill() } if (sys.__strokeStyle !== '') { sys.__ctx.stroke() } }, return_none: true }, '全描画クリア': { // @ 描画中のキャンバスをクリアする。 // @ ぜんびょうがくりあ type: 'func', josi: [], pure: true, fn: function (sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.clearRect(0, 0, sys.__canvas.width, sys.__canvas.height) }, return_none: true }, '描画クリア': { // @ [x, y, w, h]の範囲を描画クリア。空配列を指定すると『全描画クリア』と同じ。2要素の配列だと[0,0]を省略したのと同じ。 // @ びょうがくりあ type: 'func', josi: [['の', 'へ', 'に']], pure: true, fn: function (b: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } if (!(b instanceof Array)) { b = [] } if (b.length === 0) { b = [0, 0, sys.__canvas.width, sys.__canvas.height] } else if (b.length <= 2) { b.unshift(0) b.unshift(0) } sys.__ctx.clearRect(b[0], b[1], b[2], b[3]) }, return_none: true }, '円描画': { // @ [x, y]へrの円を描画する // @ えんびょうが type: 'func', josi: [['へ', 'に'], ['の']], pure: true, fn: function (xy: any, r: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } if (sys.__fillStyle === '' && sys.__strokeStyle === '') { return } sys.__ctx.beginPath() sys.__ctx.arc(xy[0], xy[1], r, 0, 2 * Math.PI, false) if (sys.__fillStyle !== '') { sys.__ctx.fill() } if (sys.__strokeStyle !== '') { sys.__ctx.stroke() } }, return_none: true }, '楕円描画': { // @ [x, y, x幅, y幅, 回転, 開始角, 終了角, 左回転か]に楕円を描画する // @ だえんびょうが type: 'func', josi: [['へ', 'に', 'の']], pure: true, fn: function (args: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } if (!args) { throw new Error('楕円描画の引数配列が無効です') } if (args.length < 4) { throw new Error('楕円描画の引数配列が不足しています') } if (args.length < 7) { if (!args[4]) { args[4] = 0 } if (!args[5]) { args[5] = 0 } if (!args[6]) { args[6] = Math.PI * 2 } if (!args[7]) { args[7] = true } } if (sys.__fillStyle === '' && sys.__strokeStyle === '') { return } sys.__ctx.beginPath() sys.__ctx.ellipse(...args) if (sys.__fillStyle !== '') { sys.__ctx.fill() } if (sys.__strokeStyle !== '') { sys.__ctx.stroke() } }, return_none: true }, '多角形描画': { // @ 座標配列vを指定して多角形を描画する // @ たかっけいびょうが type: 'func', josi: [['で', 'の', 'を']], pure: true, fn: function (a: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } if (sys.__fillStyle === '' && sys.__strokeStyle === '') { return } sys.__ctx.beginPath() const p = a[0] sys.__ctx.moveTo(p[0], p[1]) for (let i = 1; i < a.length; i++) { const t = a[i] sys.__ctx.lineTo(t[0], t[1]) } sys.__ctx.lineTo(p[0], p[1]) if (sys.__fillStyle !== '') { sys.__ctx.fill() } if (sys.__strokeStyle !== '') { sys.__ctx.stroke() } }, return_none: true }, '画像読': { // @ 画像のURLを読み込んでImageオブジェクトを返す。(URLにdataスキームも指定可能) // @ がぞうよむ type: 'func', josi: [['の', 'を']], pure: true, fn: function (url: any, sys: any) { const img = new window.Image() img.src = url img.crossOrigin = 'Anonymous' return img } }, '画像読待': { // @ 画像のURLを読み込んでImageオブジェクトを返す。その際、画像の読み込みが終わるまで待つ。// @ がぞうよみまつ type: 'func', josi: [['の', 'を']], pure: true, asyncFn: true, fn: function (url: any) { return new Promise((resolve, reject) => { const img = new window.Image() img.src = url img.crossOrigin = 'Anonymous' img.onload = () => { resolve(img) } img.onerror = () => { reject(new Error(`『画像読待』で読込みエラー。URL=『${url}』`)) } }) } }, '画像逐次読': { // @ (非推奨) 画像のURLを読み込んでImageオブジェクトを返す。また完了時『対象』にも代入する。『逐次実行』構文で使う。 // @ がぞうちくじよむ type: 'func', josi: [['の', 'を']], pure: true, fn: function (url: any, sys: any) { if (sys.resolve === undefined) { throw new Error('『画像逐次読』は『逐次実行』構文で使ってください。') } sys.resolveCount++ const img = new window.Image() img.src = url img.crossOrigin = 'Anonymous' img.onload = () => { sys.__setSysVar('対象', img) sys.resolve() } img.onerror = () => { sys.__setSysVar('対象', '') sys.reject() } return img } }, '画像読時': { // @ 画像のURLを読み込んでコールバック関数Fを読み込み、変数『対象』にImageオブジェクトを代入する // @ がぞうよんだとき type: 'func', josi: [['で'], ['の', 'を']], pure: true, fn: function (f: any, url: any, sys: any) { // 関数オブジェクトを得る const func = sys.__findVar(f, null) // 文字列指定なら関数に変換 // 画像を読む const img = new window.Image() img.src = url img.crossOrigin = 'Anonymous' img.onload = () => { sys.__setSysVar('対象', img) func(sys) } img.onerror = () => { sys.__setSysVar('対象', '') func(sys) } }, return_none: true }, '画像描画': { // @ 画像IMG(またはURL)を描画先座標[x,y]へ描画し、Imageオブジェクトを返す。座標には2,4,8個の引数を指定可能。 // @ がぞうびょうが type: 'func', josi: [['の', 'を'], ['へ', 'に']], pure: true, fn: function (img: any, xy: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } const drawFunc = (im: any, ctx: any) => { if (xy.length === 2) { ctx.drawImage(im, xy[0], xy[1]) } else if (xy.length === 4) { ctx.drawImage(im, xy[0], xy[1], xy[2], xy[3]) } else if (xy.length === 8) { ctx.drawImage(im, xy[0], xy[1], xy[2], xy[3], xy[4], xy[5], xy[6], xy[7]) } else { throw new Error('『画像描画』の第二引数の配列要素は2,4,8個のいずれかです。') } } if (typeof img === 'string') { const image = new window.Image() image.src = img image.crossOrigin = 'Anonymous' image.onload = () => { drawFunc(image, sys.__ctx) } return image } else { drawFunc(img, sys.__ctx) return img } }, return_none: false }, '画像部分描画': { // @ 画像IMG(またはURL)の座標[sx, sy, sw, sh]を描画先座標[dx, dy, dw, dh]へ描画し、Imageオブジェクトを返す // @ がぞうぶぶんびょうが type: 'func', josi: [['の'], ['を', 'から'], ['へ', 'に']], pure: true, fn: function (img: any, sxy: any, dxy: any, sys: any) { const errArgLen = '『画像部分描画』に使える引数は画像と、描画する座標へ2つか、' + '描画する座標とその位置の4つか、使用する座標と使用する位置と描画する座標と大きさの8つだけです。' if (img && sxy) { if (!Array.isArray(sxy) && Array.isArray(img)) { // 逆になっていれば入れ替える // eslint-disable-next-line no-proto if (typeof sxy === 'string' || String(sxy.__proto__) === '[object HTMLImageElement]') { const sw = img img = sxy sxy = sw } } } if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } const drawFunc = (im: any, ctx: any) => { if (!dxy) { if (!sxy) { ctx.drawImage(im) } else if (sxy.length >= 2) { // もしsxyがあるのにdxyがなかったらdxyを代わりにする dxy = sxy sxy = undefined } } if (dxy.length === 2) { ctx.drawImage(im, dxy[0], dxy[1]) } else if (dxy.length === 4) { if (!sxy) { ctx.drawImage(im, dxy[0], dxy[1], dxy[2], dxy[3]) } else if (sxy.length === 4) { ctx.drawImage(im, sxy[0], sxy[1], sxy[2], sxy[3], dxy[0], dxy[1], dxy[2], dxy[3]) } else { throw new Error(errArgLen) } } else { throw new Error(errArgLen) } } if (typeof img === 'string') { const image = new window.Image() image.src = img image.crossOrigin = 'Anonymous' image.onload = () => { drawFunc(image, sys.__ctx) } return image } else { drawFunc(img, sys.__ctx) return img } }, return_none: false }, '描画フォント設定': { // @ 描画フォントを指定する(CSSのフォント設定と同じ 例「36px Aria」)。フォントサイズのみの指定も可。 // @ びょうがふぉんとせってい type: 'func', josi: [['を', 'の', 'で', 'に']], pure: true, fn: function (n: any, sys: any) { // 数値だけならフォントサイズのみの指定 if (typeof n === 'number') { n = n + 'px sans-serif' } // ピクセル数のみの指定なら適当にフォントを足す if (/^[0-9]+(px|em)$/.test(n)) { n = n + ' sans-serif' } sys.__ctx.font = n }, return_none: true }, '文字描画': { // @ [x, y]へテキストSを描画する(描画フォント設定でサイズなど指定) // @ もじびょうが type: 'func', josi: [['へ', 'に'], ['の', 'を']], pure: true, fn: function (xy: any, s: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.fillText(s, xy[0], xy[1]) }, return_none: true }, '文字描画幅取得': { // @ テキストSを指定して文字の描画幅を取得する // @ もじびょうがはばしゅとく type: 'func', josi: [['の']], pure: true, fn: function (s: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } return sys.__ctx.measureText(s) }, return_none: false }, '描画起点設定': { // @ 描画位置の起点を[x,y]へ設定する(translate) // @ びょうがきてんせってい type: 'func', josi: [['へ', 'に']], pure: true, fn: function (xy: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.translate(xy[0], xy[1]) }, return_none: true }, '描画回転': { // @ 描画内容をA度だけ回転する(rotate) // @ びょうがかいてん type: 'func', josi: [['だけ', 'に', 'へ']], pure: true, fn: function (a: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.rotate(a * Math.PI / 180) }, return_none: true }, '描画拡大': { // @ 描画内容を[x方向,y方向]だけ拡大する(scale) // @ びょうがかくだい type: 'func', josi: [['だけ', 'に', 'へ']], pure: true, fn: function (xy: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.scale(xy[0], xy[1]) }, return_none: true }, '描画変換マトリクス設定': { // @ 描画内容を[a,b,c,d,e,f]の変換マトリクスに設定。既存内容を破棄して設定(setTransform) // @ びょうがへんかんまとりくすせってい type: 'func', josi: [['だけ', 'に', 'へ']], pure: true, fn: function (a: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.setTransform(a[0], a[1], a[2], a[3], a[4], a[5], a[6]) }, return_none: true }, '描画変換マトリクス追加': { // @ 描画内容を[a,b,c,d,e,f]のマトリクスで変換。既存のマトリクスに掛け合わせる(transform) // @ びょうがへんかんまとりくすついか type: 'func', josi: [['だけ', 'に', 'へ']], pure: true, fn: function (a: any, sys: any) { if (!sys.__ctx) { throw new Error(errMsgCanvasInit) } sys.__ctx.transform(a[0], a[1], a[2], a[3], a[4], a[5], a[6]) }, return_none: true }, '描画データURL変換': { // @ 描画内容をPNG形式のデータURLに変換して得る。 // @ びょうがでーたURLへんかん type: 'func', josi: [], pure: true, fn: function (sys: any) { const cv = sys.__getSysVar('描画中キャンバス') const url = cv.toDataURL('image/png') return url } }, '描画データBLOB変換': { // @ 描画内容をPNG形式のBLOBオブジェクトに変換して戻す。 // @ びょうがでーたBLOBへんかん type: 'func', josi: [], pure: true, asyncFn: true, fn: function (sys: any) { return new Promise((resolve, reject) => { const cv = sys.__getSysVar('描画中キャンバス') cv.toBlob((result: any) => { resolve(result) }, 'image/png') }) } }, '描画ダウンロードリンク作成': { // @ 描画内容をPNG形式のデータURLに変換してDOMに設定する。 // @ びょうがだうんろーどりんくさくせい type: 'func', josi: [['へ', 'に']], pure: true, fn: function (dom: any, sys: any) { if (typeof dom === 'string') { dom = document.querySelector(dom) } if (!dom) { throw new Error('『描画ダウンロードリンク作成』でDOMが見当たりません。') } const cv = sys.__getSysVar('描画中キャンバス') if (!cv) { throw new Error('『描画ダウンロード』で描画中キャンバスが設定されていません。') } dom.href = cv.toDataURL('image/png') dom.download = 'canvas.png' }, return_none: true }, '描画ダウンロード': { // @ 描画内容をPNG形式のデータURLに変換してダウンロードする。(「クリックした時」などと組み合わせて使う) // @ びょうがだうんろーど type: 'func', josi: [], pure: true, fn: function (sys: any) { const cv = sys.__getSysVar('描画中キャンバス') if (!cv) { throw new Error('『描画ダウンロード』で描画中キャンバスが設定されていません。') } const a = document.createElement('a') a.href = cv.toDataURL('image/png') a.download = 'canvas.png' a.click() return true } } }