微信小游戏为何fillText绘制的文字是模糊的?

新冠防疫隔离在家,无聊得紧,就写写微信小游戏来玩。

开始发现字体是模糊的,图片也比较模糊。

微信小游戏为何fillText绘制的文字是模糊的?_第1张图片

查了官方文档,微信官方说调整了canvas的缩放策略,它把物理像素和逻辑像素自动做了缩放,使我们不用考虑pixelRatio,因此字体和图片都模糊了,如果要显示高清,就要自己处理了。

官方说明如下:

https://developers.weixin.qq.com/community/develop/doc/00040c9903023848e0d7bd6205a401?highLine=%25E6%2596%2587%25E5%25AD%2597%25E6%25A8%25A1%25E7%25B3%258A

要处理高清,就要把canvas的大小乘以pixelRatio倍,如:

let sysInfo = wx.getSystemInfoSync();
canvas.width = sysInfo.screenWidth * sysInfo.pixelRatio;
canvas.height = sysInfo.screenHeight * sysInfo.pixelRatio;

同时,原来的fillRect,lineTo,moveTo......等等函数,位置大小都要乘以pixelRatio倍。为了简化修改,试了一下hook override,写一个文件wxhHook.js,把这些函数一次修改掉:

/**
 * 画布缩放,只有sysInfo.pixelRatio扩大画布,贴图和文字才会清晰,但是离屏画布复制到前景时变慢很多。
 */

//如果要扩大画布(高清),注释掉这一行
//wx.tmGlobal.sysInfo.pixelRatio = 1;

wx.tmGlobal.canvas.width = wx.tmGlobal.sysInfo.screenWidth * wx.tmGlobal.sysInfo.pixelRatio;
wx.tmGlobal.canvas.height = wx.tmGlobal.sysInfo.screenHeight * wx.tmGlobal.sysInfo.pixelRatio;

wx.tmGlobal.canvas_bkg.width = wx.tmGlobal.sysInfo.screenWidth * wx.tmGlobal.sysInfo.pixelRatio;
wx.tmGlobal.canvas_bkg.height = wx.tmGlobal.sysInfo.screenHeight * wx.tmGlobal.sysInfo.pixelRatio;

wx.tmGlobal.canvas_qipan.width = wx.tmGlobal.sysInfo.screenWidth * wx.tmGlobal.sysInfo.pixelRatio;
wx.tmGlobal.canvas_qipan.height = wx.tmGlobal.sysInfo.screenHeight * wx.tmGlobal.sysInfo.pixelRatio;

wx.tmGlobal.canvas_score.width = wx.tmGlobal.sysInfo.screenWidth * wx.tmGlobal.sysInfo.pixelRatio;
wx.tmGlobal.canvas_score.height = wx.tmGlobal.sysInfo.screenHeight * wx.tmGlobal.sysInfo.pixelRatio;

let CanvasRenderingContext2D = wx.tmGlobal.context.constructor;

CanvasRenderingContext2D.prototype._moveTo=CanvasRenderingContext2D.prototype.moveTo;
CanvasRenderingContext2D.prototype.moveTo = function (x, y) {
  return CanvasRenderingContext2D.prototype._moveTo.call(this,
    x * wx.tmGlobal.sysInfo.pixelRatio,
    y * wx.tmGlobal.sysInfo.pixelRatio);
}

CanvasRenderingContext2D.prototype._lineTo = CanvasRenderingContext2D.prototype.lineTo;
CanvasRenderingContext2D.prototype.lineTo = function (x, y) {
  return CanvasRenderingContext2D.prototype._lineTo.call(this,
    x * wx.tmGlobal.sysInfo.pixelRatio,
    y * wx.tmGlobal.sysInfo.pixelRatio);
}

CanvasRenderingContext2D.prototype._strokeRect = CanvasRenderingContext2D.prototype.strokeRect;
CanvasRenderingContext2D.prototype.strokeRect = function (x, y, w, h) {
  return CanvasRenderingContext2D.prototype._strokeRect.call(this,
    x * wx.tmGlobal.sysInfo.pixelRatio,
    y * wx.tmGlobal.sysInfo.pixelRatio,
    w * wx.tmGlobal.sysInfo.pixelRatio,
    h * wx.tmGlobal.sysInfo.pixelRatio);
};

CanvasRenderingContext2D.prototype._fillRect = CanvasRenderingContext2D.prototype.fillRect;
CanvasRenderingContext2D.prototype.fillRect = function (x, y, w, h) {
  return CanvasRenderingContext2D.prototype._fillRect.call(this,
    x * wx.tmGlobal.sysInfo.pixelRatio,
    y * wx.tmGlobal.sysInfo.pixelRatio,
    w * wx.tmGlobal.sysInfo.pixelRatio,
    h * wx.tmGlobal.sysInfo.pixelRatio);
};

CanvasRenderingContext2D.prototype._rect = CanvasRenderingContext2D.prototype.rect;
CanvasRenderingContext2D.prototype.rect = function (x, y, w, h) {
  return CanvasRenderingContext2D.prototype._rect.call(this,
    x * wx.tmGlobal.sysInfo.pixelRatio,
    y * wx.tmGlobal.sysInfo.pixelRatio,
    w * wx.tmGlobal.sysInfo.pixelRatio,
    h * wx.tmGlobal.sysInfo.pixelRatio);
};

CanvasRenderingContext2D.prototype._clearRect = CanvasRenderingContext2D.prototype.clearRect;
CanvasRenderingContext2D.prototype.clearRect = function (x, y, w, h) {
  return CanvasRenderingContext2D.prototype._clearRect.call(this,
    x * wx.tmGlobal.sysInfo.pixelRatio,
    y * wx.tmGlobal.sysInfo.pixelRatio,
    w * wx.tmGlobal.sysInfo.pixelRatio,
    h * wx.tmGlobal.sysInfo.pixelRatio);
};

//img整图缩放绘制,如果是从img扣去部分来绘制,请使用_drawImage,并把sx,sy,sw,sh也乘以pixelRatio
CanvasRenderingContext2D.prototype._drawImage = CanvasRenderingContext2D.prototype.drawImage;
CanvasRenderingContext2D.prototype.drawImage = function (img) {
  //console.log(arguments);
  let params = new Array(9);
  if (arguments.length == 3) {
    params[0] = arguments[0];        //img
    params[1] = 0;                   //sx
    params[2] = 0;                   //sy
    params[3] = arguments[0].width;  //sw
    params[4] = arguments[0].height; //sh
    params[5] = arguments[1];        //dx
    params[6] = arguments[2];        //dy
    params[7] = arguments[0].width;  //dw
    params[8] = arguments[0].height; //dh
  }
  else if (arguments.length == 5) {
    params[0] = arguments[0];        //img
    params[1] = 0;                   //sx
    params[2] = 0;                   //sy
    params[3] = arguments[0].width;  //sw
    params[4] = arguments[0].height; //sh
    params[5] = arguments[1];        //dx
    params[6] = arguments[2];        //dy
    params[7] = arguments[3];        //dw
    params[8] = arguments[4];        //dh
  }
  else params = arguments;
  for (let i = 5; i < params.length; i++) {
    params[i] = params[i] * wx.tmGlobal.sysInfo.pixelRatio;
  }
  //console.log(params);
  return CanvasRenderingContext2D.prototype._drawImage.apply(this, params);
};

CanvasRenderingContext2D.prototype._fillText = CanvasRenderingContext2D.prototype.fillText;
CanvasRenderingContext2D.prototype.fillText = function (s, x, y) {
  return CanvasRenderingContext2D.prototype._fillText.call(this,
    s, x * wx.tmGlobal.sysInfo.pixelRatio,
    y * wx.tmGlobal.sysInfo.pixelRatio);
}

CanvasRenderingContext2D.prototype._createImageData = CanvasRenderingContext2D.prototype.createImageData;
CanvasRenderingContext2D.prototype.createImageData = function (w, h) {
  return CanvasRenderingContext2D.prototype._createImageData.call(this,
    w * wx.tmGlobal.sysInfo.pixelRatio, h * wx.tmGlobal.sysInfo.pixelRatio);
}

CanvasRenderingContext2D.prototype._getImageData = CanvasRenderingContext2D.prototype.getImageData;
CanvasRenderingContext2D.prototype.getImageData = function (x, y, w, h) {
  return CanvasRenderingContext2D.prototype._getImageData.call(this,
    x * wx.tmGlobal.sysInfo.pixelRatio,
    y * wx.tmGlobal.sysInfo.pixelRatio,
    w * wx.tmGlobal.sysInfo.pixelRatio,
    h * wx.tmGlobal.sysInfo.pixelRatio);
}

CanvasRenderingContext2D.prototype._putImageData = CanvasRenderingContext2D.prototype.putImageData;
CanvasRenderingContext2D.prototype.putImageData = function (data, x, y) {
  return CanvasRenderingContext2D.prototype._putImageData.call(this, data,
    x * wx.tmGlobal.sysInfo.pixelRatio, y * wx.tmGlobal.sysInfo.pixelRatio);
}

保留了原函数,前面加了一个下划线,特殊需要调用地方使用原函数,如画布复制:

function updateCanvas(){
  //没有clearRect,感觉画面偶尔会闪一下
  wx.tmGlobal.context._clearRect(0, 0, wx.tmGlobal.canvas.width, wx.tmGlobal.canvas.height);
  if (wx.tmGlobal.context_bkg != wx.tmGlobal.context){
    //复制画布,用旧的不考虑pixelRatio的函数画
    wx.tmGlobal.context._drawImage(wx.tmGlobal.canvas_bkg,0,0);
  }
}

其它要注意的是字体,需要修改,如:

//const g_scoreFont = "14px Arial";
const g_scoreFont = 14 * wx.tmGlobal.sysInfo.pixelRatio+"px Arial";

微信小游戏为何fillText绘制的文字是模糊的?_第2张图片

你可能感兴趣的:(微信小游戏,Javascript,游戏,javascript)