drawTextContent

This commit is contained in:
oc 2019-03-23 16:44:14 +08:00
parent e0eea19d84
commit 1b0c65f6f6
4 changed files with 227 additions and 43 deletions

View File

@ -751,7 +751,7 @@ events.prototype.doAction = function () {
if (this._doAction_finishEvents()) return; if (this._doAction_finishEvents()) return;
// 当前点坐标和前缀 // 当前点坐标和前缀
var x = core.status.event.data.x, y = core.status.event.data.y; var x = core.status.event.data.x, y = core.status.event.data.y;
var prefix = [core.status.floorId || "f", x != null ? x : "x", y != null ? y : "y"].join("@"); var prefix = [core.status.floorId || ":f", x != null ? x : "x", y != null ? y : "y"].join("@");
var current = core.status.event.data.list[0]; var current = core.status.event.data.list[0];
if (this._popEvents(current, prefix)) return; if (this._popEvents(current, prefix)) return;
// 当前要执行的事件 // 当前要执行的事件
@ -1711,7 +1711,7 @@ events.prototype.setValue = function (name, value, prefix, add) {
this._setValue_setStatus(name, value); this._setValue_setStatus(name, value);
this._setValue_setItem(name, value); this._setValue_setItem(name, value);
this._setValue_setFlag(name, value); this._setValue_setFlag(name, value);
this._setValue_setSwitch(name, value); this._setValue_setSwitch(name, value, prefix);
core.updateStatusBar(); core.updateStatusBar();
} }
@ -1739,7 +1739,7 @@ events.prototype._setValue_setFlag = function (name, value) {
events.prototype._setValue_setSwitch = function (name, value, prefix) { events.prototype._setValue_setSwitch = function (name, value, prefix) {
if (name.indexOf("switch:") !== 0) return; if (name.indexOf("switch:") !== 0) return;
core.setFlag((prefix || "f@x@y") + "@" + data.name.substring(7), value); core.setFlag((prefix || ":f@x@y") + "@" + name.substring(7), value);
} }
////// 数值增减 ////// ////// 数值增减 //////

View File

@ -1169,7 +1169,7 @@ maps.prototype.getBlockInfo = function (block) {
block = this.initBlock(0, 0, block, true); block = this.initBlock(0, 0, block, true);
} }
var number = block.id, id = block.event.id, cls = block.event.cls, var number = block.id, id = block.event.id, cls = block.event.cls,
image = null, posX = 0, posY = 0, image = null, posX = 0, posY = 0, animate = block.event.animate,
height = block.event.height || 32, faceIds = {}; height = block.event.height || 32, faceIds = {};
if (id == 'none') return null; if (id == 'none') return null;
@ -1193,7 +1193,7 @@ maps.prototype.getBlockInfo = function (block) {
faceIds = block.event.faceIds || {}; faceIds = block.event.faceIds || {};
} }
return {number: number, id: id, cls: cls, image: image, posX: posX, posY: posY, height: height, faceIds: faceIds}; return {number: number, id: id, cls: cls, image: image, posX: posX, posY: posY, height: height, faceIds: faceIds, animate: animate};
} }
////// 搜索某个图块出现的所有位置 ////// ////// 搜索某个图块出现的所有位置 //////

View File

@ -174,6 +174,12 @@ ui.prototype.setTextAlign = function (name, align) {
if (ctx) ctx.textAlign = align; if (ctx) ctx.textAlign = align;
} }
////// 设置某个canvas的baseline //////
ui.prototype.setTextBaseline = function (name, baseline) {
var ctx = this.getContextByName(name);
if (ctx) ctx.textBaseline = baseline;
}
////// 计算某段文字的宽度 ////// ////// 计算某段文字的宽度 //////
ui.prototype.calWidth = function (name, text, font) { ui.prototype.calWidth = function (name, text, font) {
var ctx = this.getContextByName(name); var ctx = this.getContextByName(name);
@ -317,6 +323,43 @@ ui.prototype._drawText_setContent = function (contents, callback) {
return; return;
} }
////// 正则处理 \t[xx,yy] 问题
ui.prototype._getTitleAndIcon = function (content) {
var title = null, image = null, icon = null, height = 32, animate = 1;
content = content.replace(/(\t|\\t)\[(([^\],]+),)?([^\],]+)\]/g, function (s0, s1, s2, s3, s4) {
if (s4) {
if (s4 == 'hero') {
title = core.status.hero.name;
image = core.material.images.hero;
icon = 0;
height = core.material.icons.hero.height;
}
else if (/^[-\w.]+\.png$/.test(s4))
image = core.material.images.images[s4];
else {
var blockInfo = core.getBlockInfo(s4);
if (blockInfo != null) {
if (core.material.enemys[s4]) title = core.material.enemys[s4].name;
image = blockInfo.image;
icon = blockInfo.posX;
height = blockInfo.height;
animate = blockInfo.animate;
}
}
}
if (s3) title = s3;
return "";
});
return {
content: content,
title: title,
image: image,
icon: icon,
height: height,
animate: animate
};
}
ui.prototype.getTitleAndIcon = function (content) { ui.prototype.getTitleAndIcon = function (content) {
var id=null, name=null, image=null, icon=null, iconHeight=32, animate=null; var id=null, name=null, image=null, icon=null, iconHeight=32, animate=null;
@ -378,8 +421,8 @@ ui.prototype.getTitleAndIcon = function (content) {
}; };
} }
// 绘制选择光标 ////// 绘制选择光标
ui.prototype.drawWindowSelector = function(background,x,y,w,h) { ui.prototype.drawWindowSelector = function(background, x, y, w, h) {
w = Math.round(w), h = Math.round(h); w = Math.round(w), h = Math.round(h);
var dstImage = core.ui.createCanvas("_selector", x, y, w, h, 165); var dstImage = core.ui.createCanvas("_selector", x, y, w, h, 165);
core.setOpacity("_selector", 0.8); core.setOpacity("_selector", 0.8);
@ -397,10 +440,10 @@ ui.prototype.drawWindowSelector = function(background,x,y,w,h) {
dstImage.drawImage(background, 158, 66, 2, 28,w-2, 2, 2,h-4); dstImage.drawImage(background, 158, 66, 2, 28,w-2, 2, 2,h-4);
} }
// 绘制皮肤 ////// 绘制 WindowSkin
ui.prototype.drawWindowSkin = function(background,canvas,x,y,w,h,direction,px,py) { ui.prototype.drawWindowSkin = function(background, ctx, x, y, w, h, direction, px, py) {
// 仿RM窗口皮肤 ↓ // 仿RM窗口皮肤 ↓
var dstImage = core.getContextByName(canvas); var dstImage = core.getContextByName(ctx);
if (!dstImage) return; if (!dstImage) return;
// 绘制背景 // 绘制背景
dstImage.drawImage(background, 0, 0, 128, 128, x+2, y+2, w-4, h-4); dstImage.drawImage(background, 0, 0, 128, 128, x+2, y+2, w-4, h-4);
@ -426,7 +469,7 @@ ui.prototype.drawWindowSkin = function(background,canvas,x,y,w,h,direction,px,py
dstImage.drawImage(background, 176,48, 16, 16, x+w-16, y+h-16, 16, 16); dstImage.drawImage(background, 176,48, 16, 16, x+w-16, y+h-16, 16, 16);
// arrow // arrow
if(core.isset(px) && core.isset(py)){ if(px != null && py != null){
if(direction == 'up'){ if(direction == 'up'){
dstImage.drawImage(background,128,96,32,32,px,y+h-3,32,32); dstImage.drawImage(background,128,96,32,32,px,y+h-3,32,32);
}else if(direction == 'down') { }else if(direction == 'down') {
@ -436,57 +479,198 @@ ui.prototype.drawWindowSkin = function(background,canvas,x,y,w,h,direction,px,py
// 仿RM窗口皮肤 ↑ // 仿RM窗口皮肤 ↑
} }
// 计算有效文本框的宽度 ////// 计算有效文本框的宽度
ui.prototype.calTextBoxWidth = function (canvas, content, min_width, max_width) { ui.prototype.calTextBoxWidth = function (ctx, content, min_width, max_width) {
// 无限长度自动换行 // 无限长度自动换行
var allLines = core.splitLines(canvas, content); var allLines = core.splitLines(ctx, content);
// 如果不存在手动换行,则二分自动换行 // 如果不存在手动换行,尽量调成半行形式
if (allLines.length == 1) { if (allLines.length == 1) {
var w = core.calWidth(canvas, allLines[0]); var w = core.calWidth(ctx, allLines[0]);
if (w<min_width*2.3) return core.clamp(w / 1.4, min_width, max_width); if (w<min_width*2.3) return core.clamp(w / 1.4, min_width, max_width);
if (w<max_width*2.2) return core.clamp(w / 2.4, min_width, max_width); if (w<max_width*2.2) return core.clamp(w / 2.4, min_width, max_width);
return core.clamp(w / 3.4, min_width, max_width); return core.clamp(w / 3.4, min_width, max_width);
/*
var prefer_lines = 3;
var start = Math.floor(min_width), end = Math.floor(max_width);
while (start < end) {
var mid = Math.floor((start+end)/2);
if (core.splitLines(canvas, content, mid).length < prefer_lines)
end = mid;
else
start = mid + 1;
}
return mid;
*/
} }
// 存在手动换行:以最长的为准 // 存在手动换行:以最长的为准
else { else {
var w = 0; return core.clamp(allLines.reduce(function (pre, curr) {
allLines.forEach(function (t) { return Math.max(pre, core.calWidth(ctx, curr))
w = Math.max(w, core.calWidth(canvas, t)); }, 0), min_width, max_width);
});
return core.clamp(w, min_width, max_width);
} }
} }
ui.prototype.__getIconInfo = function (id) { ////// 处理 \i[xxx] 的问题
ui.prototype._getDrawableIconInfo = function (id) {
var image = null, icon = null; var image = null, icon = null;
["terrains","animates","items","npcs","enemys"].forEach(function (v) { ["terrains","animates","items","npcs","enemys"].forEach(function (v) {
if (core.isset(core.material.icons[v][id])) { if (core.material.icons[v][id] != null) {
image = core.material.images[v]; image = core.material.images[v];
icon = core.material.icons[v][id]; icon = core.material.icons[v][id];
} }
}); });
if (image == null) { if (image == null && id in core.statusBar.icons) {
if (id in core.statusBar.icons) { image = core.statusBar.icons[id];
image = core.statusBar.icons[id]; icon = 0;
icon = 0;
}
} }
return [image,icon]; return [image,icon];
} }
ui.prototype._buildFont = function (fontSize) {
return (core.status.textAttribute.bold?"bold ":"") + fontSize + "px " +core.status.globalAttribute.font;
}
////// 绘制一段文字到某个画布上面
// ctx要绘制到的画布
// content要绘制的内容转义字符目前只允许留 \n, \r[...] 和 \i[...]
// config绘制配置项目前暂时包含如下内容均为可选
// left, top起始点位置maxWidth单行最大宽度color默认颜色align左中右
// fontSize字体大小font字体样式lineHeight行高time打字机间隔
ui.prototype.drawTextContent = function (ctx, content, config) {
ctx = core.getContextByName(ctx);
if (!ctx) return;
// 设置默认配置项
config = core.clone(config || {});
config.left = config.left || 0;
config.right = config.left + (config.maxWidth == null ? ctx.canvas.width : config.maxWidth);
config.top = config.top || 0;
config.color = config.color || "#FFFFFF";
config.align = config.align || "left";
config.fontSize = config.fontSize || core.status.textAttribute.textfont;
config.lineHeight = config.lineHeight || (config.fontSize * 1.2);
config.time = config.time || 0;
config.index = 0;
config.changed = true;
config.currcolor = config.color;
config.offsetX = 0;
config.offsetY = 0;
// 创建一个新的临时画布
var tempCtx = document.createElement('canvas').getContext('2d');
tempCtx.canvas.height = config.lineHeight;
tempCtx.canvas.width = ctx.canvas.width;
tempCtx.textBaseline = 'top';
tempCtx.font = this._buildFont(config.fontSize);
this._drawTextContent_draw(ctx, tempCtx, content, config);
}
ui.prototype._drawTextContent_draw = function (ctx, tempCtx, content, config) {
if (config.time == 0) {
while (!core.ui._drawTextContent_next(ctx, tempCtx, content, config));
core.ui._drawTextContent_drawLineToCtx(ctx, tempCtx, content, config);
}
else {
core.status.event.interval = setInterval(function () {
config.changed = true;
if (!core.ui._drawTextContent_next(ctx, tempCtx, content, config)) {
clearInterval(core.status.event.interval);
core.status.event.interval = null;
core.ui._drawTextContent_drawLineToCtx(ctx, tempCtx, content, config);
}
}, time);
}
}
// 进行下一次绘制
ui.prototype._drawTextContent_next = function (ctx, tempCtx, content, config) {
if (config.index >= content.length) return false;
// 是否需要改变颜色
if (config.changed) {
core.setFillStyle(tempCtx, config.currcolor);
config.changed = false;
}
// get next character
var ch = content.charAt(config.index++);
return this._drawTextContent_drawChar(ctx, tempCtx, content, config, ch);
}
// 绘制下一个字符
ui.prototype._drawTextContent_drawChar = function (ctx, tempCtx, content, config, ch) {
// \n, \\n
if (ch == '\n' || (ch=='\\' && content.charAt(config.index)=='n')) {
this._drawTextContent_drawLineToCtx(ctx, tempCtx, content, config);
if (ch=='\\') config.index++;
return this._drawTextContent_next(ctx, tempCtx, content, config);
}
// \r, \\r
if (ch == '\r' || (ch=='\\' && content.charAt(config.index)=='r')) {
if (ch == '\\') config.index++;
return this._drawTextContent_changeColor(ctx, tempCtx, content, config);
}
// \\i 绘制图标
if (ch == '\\' && content.charAt(config.index)=='i') {
return this._drawTextContent_drawIcon(ctx, tempCtx, content, config);
}
// 检查是不是自动换行
var charwidth = core.calWidth(tempCtx, ch);
if (config.maxWidth != null && config.offsetX + charwidth > config.maxWidth) {
this._drawTextContent_drawLineToCtx(ctx, tempCtx, content, config);
config.index--;
return this._drawTextContent_next(ctx, tempCtx, content, config);
}
// 输出
core.fillText(tempCtx, ch, config.offsetX, 0);
config.offsetX += charwidth;
return true;
}
// 从临时画布绘制到正式画布上面
ui.prototype._drawTextContent_drawLineToCtx = function (ctx, tempCtx, content, config) {
// 计算坐标,宽高
var left = config.left, top = config.top + config.offsetY;
var width = config.offsetX, height = config.lineHeight;
// 计算起点横坐标
if (config.align == 'center')
left = (config.left + config.right - width) / 2;
else if (config.align == 'right')
left = config.right - width;
core.drawImage(ctx, tempCtx.canvas, 0, 0, width, height, left, top, width, height);
config.offsetX = 0;
config.offsetY += config.lineHeight;
}
ui.prototype._drawTextContent_changeColor = function (ctx, tempCtx, content, config) {
config.changed = true;
// 检查是不是 []
var index = config.index, index2;
if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) {
// 变色
var str = content.substring(index+1, index2);
if (str=="") config.currcolor = config.color;
else config.currcolor = str;
config.index = index2 + 1;
}
else config.currcolor = color;
return this._drawTextContent_next(ctx, tempCtx,content, config);
}
ui.prototype._drawTextContent_drawIcon = function (ctx, tempCtx, content, config) {
// 绘制一个 \i 效果
var index = config.index, index2;
if (content.charAt(config.index+1) == '[' && ((index2=content.indexOf(']', index+1))>=0)) {
var str = content.substring(index+2, index2);
// --- 获得图标
var iconInfo = core.ui._getDrawableIconInfo(str), image = iconInfo[0], icon = iconInfo[1];
if (image == null) return this._drawTextContent_next(ctx, tempCtx, content, config);
// 检查自动换行
var width = config.fontSize + 2, left = config.offsetX + 2, top = (config.lineHeight - width) / 2;
if (config.maxWidth != null && left + width > config.maxWidth) {
this._drawTextContent_drawLineToCtx(ctx, tempCtx, content, config);
config.index--;
this._drawTextContent_next(ctx, tempCtx, content, config);
}
// 绘制到画布上
core.drawImage(tempCtx, image, 0, 32*icon, 32, 32, left, top, width, width);
config.offsetX += width + 6;
config.index = index2 + 1;
return true;
}
return this._drawTextContent_next(ctx, tempCtx, content, config);
}
ui.prototype.__drawText = function (canvas, content, content_left, content_top, valid_width, ui.prototype.__drawText = function (canvas, content, content_left, content_top, valid_width,
color, per_height, text_font, time) { color, per_height, text_font, time) {
core.setTextAlign(canvas, 'left'); core.setTextAlign(canvas, 'left');
@ -534,7 +718,7 @@ ui.prototype.__drawText = function (canvas, content, content_left, content_top,
if (content.charAt(index+1) == '[' && ((index2=content.indexOf(']', index+1))>=0)) { if (content.charAt(index+1) == '[' && ((index2=content.indexOf(']', index+1))>=0)) {
var str = content.substring(index+2, index2); var str = content.substring(index+2, index2);
// --- 获得图标 // --- 获得图标
var iconInfo = core.ui.__getIconInfo(str), image = iconInfo[0], icon = iconInfo[1]; var iconInfo = core.ui._getDrawableIconInfo(str), image = iconInfo[0], icon = iconInfo[1];
if (image != null) { if (image != null) {
if (core.isset(valid_width) && offsetx + text_font + 6 > content_left + valid_width) { if (core.isset(valid_width) && offsetx + text_font + 6 > content_left + valid_width) {
index --; index --;
@ -991,7 +1175,7 @@ ui.prototype.drawChoices = function(content, choices) {
core.setFillStyle('ui', color); core.setFillStyle('ui', color);
var offset = 208; var offset = 208;
if (core.isset(choices[i].icon)) { if (core.isset(choices[i].icon)) {
var iconInfo = this.__getIconInfo(choices[i].icon), image = iconInfo[0], icon = iconInfo[1]; var iconInfo = this._getDrawableIconInfo(choices[i].icon), image = iconInfo[0], icon = iconInfo[1];
if (image != null) { if (image != null) {
core.drawImage('ui', image, 0, 32*icon, 32, 32, core.drawImage('ui', image, 0, 32*icon, 32, 32,
208 - choices[i].width/2, choice_top + 32*i - 17, 22, 22); 208 - choices[i].width/2, choice_top + 32*i - 17, 22, 22);

View File

@ -66,7 +66,7 @@ utils.prototype.calValue = function (value, prefix, need, times) {
value = value.replace(/status:([\w\d_]+)/g, "core.getStatus('$1')"); value = value.replace(/status:([\w\d_]+)/g, "core.getStatus('$1')");
value = value.replace(/item:([\w\d_]+)/g, "core.itemCount('$1')"); value = value.replace(/item:([\w\d_]+)/g, "core.itemCount('$1')");
value = value.replace(/flag:([\w\d_]+)/g, "core.getFlag('$1', 0)"); value = value.replace(/flag:([\w\d_]+)/g, "core.getFlag('$1', 0)");
value = value.replace(/switch:([\w\d_]+)/g, "core.getFlag('" + (prefix || "global") + "@$1', 0)"); value = value.replace(/switch:([\w\d_]+)/g, "core.getFlag('" + (prefix || ":f@x@y") + "@$1', 0)");
return eval(value); return eval(value);
} }
if (value instanceof Function) { if (value instanceof Function) {