| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- /*
- * Tencent is pleased to support the open source community by making vap available.
- *
- * Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
- *
- * Licensed under the MIT License (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- *
- * http://opensource.org/licenses/MIT
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is
- * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific language governing permissions and
- * limitations under the License.
- */
- export default class FrameParser {
- constructor(source, headData) {
- this.config = source || {};
- this.headData = headData;
- this.frame = [];
- this.textureMap = {}
- }
- private config;
- private headData;
- private frame;
- private textureMap;
- private canvas:HTMLCanvasElement;
- private ctx:CanvasRenderingContext2D | null;
- private srcData;
- async init() {
- this.initCanvas();
- // 判断是url还是json对象
- if(/\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]\.json$/.test(this.config)){
- this.config = await this.getConfigBySrc(this.config);
- }
- await this.parseSrc(this.config);
- this.canvas.parentNode.removeChild(this.canvas);
- this.frame = this.config.frame || [];
- return this;
- }
- initCanvas() {
- const canvas = document.createElement('canvas');
- const ctx = canvas.getContext('2d');
- canvas.style.display = 'none';
- document.body.appendChild(canvas);
- this.ctx = ctx;
- this.canvas = canvas;
- }
- loadImg(url:string) {
- return new Promise((resolve, reject) => {
- // console.log('load img:', url)
- const img = new Image();
- img.crossOrigin = 'anonymous';
- img.onload = function() {
- resolve(this);
- };
- img.onerror = function(e) {
- console.error('frame 资源加载失败:' + url);
- reject(new Error('frame 资源加载失败:' + url));
- };
- img.src = url;
- })
- }
- parseSrc(dataJson) {
- const src = (this.srcData = {});
- return Promise.all(
- (dataJson.src || []).map(async item => {
- item.img = null;
- if (!this.headData[item.srcTag.slice(1, item.srcTag.length - 1)]) {
- console.warn(`vap: 融合信息没有传入:${item.srcTag}`);
- } else {
- if (item.srcType === 'txt') {
- if (this.headData['fontStyle'] && !item['fontStyle']) {
- item['fontStyle'] = this.headData['fontStyle']
- }
- item.textStr = item.srcTag.replace(/\[(.*)\]/, ($0, $1) => {
- return this.headData[$1];
- });
- item.img = this.makeTextImg(item);
- } else if (item.srcType === 'img') {
- item.imgUrl = item.srcTag.replace(/\[(.*)\]/, ($0, $1) => {
- return this.headData[$1]
- });
- try {
- item.img = await this.loadImg(item.imgUrl + '?t=' + Date.now());
- } catch (e) {}
- }
- if (item.img) {
- src[item.srcId] = item;
- }
- }
- })
- )
- }
- /**
- * 下载json文件
- * @param jsonUrl json外链
- * @returns {Promise}
- */
- getConfigBySrc(jsonUrl:string) {
- return new Promise((resolve, reject) => {
- const xhr = new XMLHttpRequest();
- xhr.open("GET", jsonUrl, true);
- xhr.responseType = "json";
- xhr.onload = function() {
- if (xhr.status === 200 || xhr.status === 304 && xhr.response) {
- const res = xhr.response;
- resolve(res);
- } else {
- reject(new Error("http response invalid" + xhr.status));
- }
- };
- xhr.send();
- });
- }
- /**
- * 文字转换图片
- * @param item
- */
- makeTextImg(item) {
- const { textStr, w, h, color, style, fontStyle } = item
- const ctx = this.ctx;
- ctx.canvas.width = w;
- ctx.canvas.height = h;
- ctx.textBaseline = 'middle';
- ctx.textAlign = 'center';
- const getFontStyle = function() {
- const fontSize = Math.min(w / textStr.length, h - 8); // 需留一定间隙
- const font = [`${fontSize}px`, 'Arial'];
- if (style === 'b') {
- font.unshift('bold');
- }
- return font.join(' ');
- }
- if (!fontStyle) {
- ctx.font = getFontStyle();
- ctx.fillStyle = color;
- } else if (typeof fontStyle == 'string') {
- ctx.font = fontStyle;
- ctx.fillStyle = color;
- } else if (typeof fontStyle == 'object') {
- ctx.font = fontStyle['font'] || getFontStyle();
- ctx.fillStyle = fontStyle['color'] || color;
- } else if (typeof fontStyle == 'function') {
- ctx.font = getFontStyle();
- ctx.fillStyle = color;
- fontStyle.call(null, ctx, item);
- }
- ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
- ctx.fillText(textStr, w / 2, h / 2);
- // console.log('frame : ' + textStr, ctx.canvas.toDataURL('image/png'))
- return ctx.getImageData(0, 0, w, h);
- }
- getFrame(frame) {
- return this.frame.find(item => {
- return item.i === frame;
- })
- }
- }
|