我在做canvas时遇到了这个问题,画完了看起来好好的,一放大,就糊的不能看,甚至有时候不放大也显得有些糊。解决的方法是放大绘制,缩小观看。就像这样:
// html
<canvas width="200" height="200"></canvas>
// css
canvas {
width: 100px;
height: 100px;
}
- 在设定style时,如果大小和绘制大小不一致,会对canvas进行缩放,而不是裁剪。
- 可以采用固定放大比例,或者固定绘制大小(4k分辨率)两种方式,我这里用的是固定放大比例
在demo最开始只有html和css时是这样的:
// html
<body>
<div class="box">
<canvas></canvas>
</div>
<script src="a.js"></script>
</body>
// css
body {
margin: 0;
font-size: 0;
}
.box {
display: flex;
width: 100vw;
height: 100vh;
}
canvas {
margin: auto auto;
width: 80%;
height: 80%;
border: 2px solid red;
}
刷新页面会得到一个居中的大红框
添加js:
class Demo {
constructor() {
this.cns = null // canvas对象
this.W = 0 // 宽高
this.H = 0
this.k = 2 // 缩放比例
this.initDom()
}
initDom() {
let dom = document.querySelector('canvas')
this.cns = dom.getContext('2d')
this.W = dom.offsetWidth
this.H = dom.offsetHeight
let k = this.k
dom.width = this.W * k
dom.height = this.H * k
}
}
let demo = new Demo();
这样就得到了2倍绘制区域的canvas。
如果想要在左上角绘制一个100 * 100的正方形
draw() {
let cns = this.cns
let k = this.k
cns.fillRect(0, 0, 100 * k, 100 * k)
}
每个不是0的数都要乘一下这个k,写起来真的好麻烦,写个函数就好啦。这个函数肯定要写在class内部,因为是绘制专用的。
a(flt) {
return flt * this.k | 0
}
但是每次都敲this.a(100)看起来太蠢了,即使这个函数名只有一个字母。如果我们拷贝这个函数 let a = this.a,很遗憾,这会无法找到k,拷贝的时候this变化了。我对call的使用并不熟悉,这里用call我只能写成
cns.fillRect(0, 0, f.call(this, 100), f.call(this, 100))
不知道有没有可以简单的写法?在这里做一个柯里化我觉着还是比较好的。
首先需要一个转化柯里化的函数:
function curry(def, ...first) {
return function (...other) {
let all = [...first, ...other]
return def.apply(null, all)
}
}
// 高程604页,这里我只是用了新语法,书中原函数:
function curry(fn) {
var args = Array.prototype.slice.call(arguments, 1)
return function () {
var innerArgs = Array.prototype.slice.call(arguments)
var finalArgs = args.concat(innerArgs)
return fn.apply(null, finalArgs)
}
}
在class内这样写:
draw() {
let cns = this.cns
let f = curry(this.floot2int, this.k)
cns.fillRect(0, 0, f(100), f(100))
}
floot2int(k, flt) {
return k * flt | 0
}
f(100)这个写法实在是不能再简单了。
完整的js:
class Demo {
constructor() {
this.cns = null // canvas对象
this.W = 0 // 宽高
this.H = 0
this.k = 2 // 缩放比例
this.initDom()
this.draw()
}
initDom() {
let dom = document.querySelector('canvas')
this.cns = dom.getContext('2d')
this.W = dom.offsetWidth
this.H = dom.offsetHeight
let k = this.k
dom.width = this.W * k
dom.height = this.H * k
}
draw() {
let cns = this.cns
let f = curry(this.floot2int, this.k)
cns.fillRect(0, 0, f(100), f(100))
}
floot2int(k, flt) {
return k * flt | 0
}
}
let demo = new Demo();
function curry(fn, ...first) {
return function (...other) {
let all = [...first, ...other]
return fn.apply(null, all)
}
}