javascript - 使 JavaScript 画布背景透明
问题描述
我试图让这个 Codepen 的背景透明https://codepen.io/scorch/pen/BZjbmW。我想让漩涡在不同的背景上,而不是在规定的 Codepen 上的彩色背景。
我试过添加 css 代码,但似乎没有做任何事情。我尝试弄乱 Canvas RGB,但似乎也没有做任何事情。
// create a canvas element
var canvas = document.createElement("canvas")
// attach element to DOM
document.getElementsByTagName("body")[0].appendChild(canvas)
// background color [r, g, b]
var bg = [20, 0, 30]
var wh = window.innerHeight
// get the canvas context (this is the part we draw to)
var ctx = canvas.getContext("2d")
function setup() {
// setup the canvas size to match the window
canvas.width = window.innerWidth
canvas.height = window.innerHeight
wh = window.innerWidth < window.innerHeight ? window.innerWidth : window.innerHeight
// set the 0,0 point to the middle of the canvas, this is not necessary but it can be handy
ctx.translate(canvas.width / 2, canvas.height / 2)
fill(bg, 1)
}
// fill entire canvas with a preset color
function fill(rgb, amt) {
ctx.beginPath(); // start path
ctx.rect(-canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height) // set rectangle to be the same size as the window
ctx.fillStyle = `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${amt})` // use the rgb array/color for fill, and amt for opacity
ctx.fill() // do the drawing
}
function drawCircle(x, y, r, color) {
ctx.beginPath()
ctx.arc(x, y, r, 0, 2 * Math.PI)
ctx.fillStyle = color || 'white'
ctx.fill()
ctx.closePath()
}
function Particle() {
// initialize loopers with random trange and offset
this.loop1 = new Looper(500 + 200 * Math.random(), 860 * Math.random())
this.loop2 = new Looper(320 + 70 * Math.random(), 20 * Math.random())
this.loop3 = new Looper(120 + 20 * Math.random(), 140 * Math.random())
this.history = []
this.history_max = 40
// this.x = null
// this.y = null
this.offset = Math.random() // some color offset for the color
this.draw = function() {
// set x,y, radius, and color params
var x = this.loop1.sin * (wh / 4 - 10) + this.loop2.sin * (wh / 6 - 10) + this.loop3.sin * 60
var y = this.loop1.cos * (wh / 4 - 10) + this.loop2.cos * (wh / 6 - 10) + this.loop3.cos * 10
var r = 0.2 + 3 * this.loop3.sinNorm * this.loop3.cosNorm // set the radius
var c = `hsla(${280 + 60 * (this.loop3.cosNorm + this.offset) * this.loop2.sinNorm}, ${100}%, ${50 + 10 * this.loop3.sin}%, ${1})`
ctx.beginPath()
ctx.strokeStyle = c
ctx.lineCap = 'round'
ctx.lineWidth = r
var tx = x
var ty = y
for (var i = 0; i < Math.min(this.history_max * this.loop3.cosNorm, this.history.length); i++) {
ctx.moveTo(tx, ty)
tx = this.history[i][0]
ty = this.history[i][1]
ctx.lineTo(tx, ty)
}
ctx.stroke()
drawCircle(x, y, r * 2 + 3, c); // draw the circle
this.loop1.update() // update looper
this.loop2.update() // update looper
this.loop3.update() // update looper
this.history.unshift([x, y])
if (this.history.length > this.history_max) {
this.history.pop()
}
}
}
// initialize a set of particle
var particles = []
for (var i = 0; i < 90; i++) {
particles.push(new Particle())
}
function draw() {
// fill context with background color
fill(bg, 0.36)
// update all the particles
for (var i = 0; i < particles.length; i++) {
particles[i].draw() // do it once
}
// this is a draw loop, this will execute frequently and is comparable to EnterFrame on other platform
window.requestAnimationFrame(function() {
draw()
})
}
// start enterFrame loop
window.requestAnimationFrame(draw);
// force running setup
setup()
// re-setup canvas when the size of the window changes
window.addEventListener("resize", setup)
// create a class to hold value and have built in incrementing functionality
function Looper(steps, start) {
this.val = start || 0 // set value to start value if defined, or 1
this.steps = steps || 100 // set steps to passed value or default to 100
this.norm = this.val / this.range // initialize normalized value (between 0 and 1)
this.sin = Math.sin(this.norm * Math.PI * 2) // get sine value from norm normalized to [0, 2PI]
this.sinNorm = (this.sin + 1) / 2 // normalize sin to [0,1]
this.cos = Math.cos(this.norm * Math.PI * 2) // get cosine value from norm normalized to [0, 2PI]
this.cosNorm = (this.cos + 1) / 2 // normalize cos to [0,1]
this.update = function() {
this.val = (this.val + 1) % this.steps // update value
this.norm = this.val / this.steps // update normalize value (between 0 and 1)
this.sin = Math.sin(this.norm * Math.PI * 2) // get sine value from norm normalized to [0, 2PI]
this.sinNorm = (this.sin + 1) / 2 // normalize sine to [0,1]
this.cos = Math.cos(this.norm * Math.PI * 2) // get cosine value from norm normalized to [0, 2PI]
this.cosNorm = (this.cos + 1) / 2 // normalize cos to [0,1]
}
}
解决方案
ctx.fillStyle =rgba(255,255,255,0)
// create a canvas element
var canvas = document.createElement("canvas")
// attach element to DOM
document.getElementsByTagName("body")[0].appendChild(canvas)
// background color [r, g, b]
var bg = [20, 0, 30]
var wh = window.innerHeight
// get the canvas context (this is the part we draw to)
var ctx = canvas.getContext("2d")
function setup() {
// setup the canvas size to match the window
canvas.width = window.innerWidth
canvas.height = window.innerHeight
wh = window.innerWidth < window.innerHeight ? window.innerWidth : window.innerHeight
// set the 0,0 point to the middle of the canvas, this is not necessary but it can be handy
ctx.translate(canvas.width / 2, canvas.height / 2)
fill(bg, 1)
}
// fill entire canvas with a preset color
function fill(rgb, amt) {
ctx.beginPath(); // start path
ctx.rect(-canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height) // set rectangle to be the same size as the window
ctx.fillStyle = `rgba(255,255,255,0)` // use the rgb array/color for fill, and amt for opacity
ctx.fill() // do the drawing
}
function drawCircle(x, y, r, color) {
ctx.beginPath()
ctx.arc(x, y, r, 0, 2 * Math.PI)
ctx.fillStyle = color || 'white'
ctx.fill()
ctx.closePath()
}
function Particle() {
// initialize loopers with random trange and offset
this.loop1 = new Looper(500 + 200 * Math.random(), 860 * Math.random())
this.loop2 = new Looper(320 + 70 * Math.random(), 20 * Math.random())
this.loop3 = new Looper(120 + 20 * Math.random(), 140 * Math.random())
this.history = []
this.history_max = 40
// this.x = null
// this.y = null
this.offset = Math.random() // some color offset for the color
this.draw = function() {
// set x,y, radius, and color params
var x = this.loop1.sin * (wh / 4 - 10) + this.loop2.sin * (wh / 6 - 10) + this.loop3.sin * 60
var y = this.loop1.cos * (wh / 4 - 10) + this.loop2.cos * (wh / 6 - 10) + this.loop3.cos * 10
var r = 0.2 + 3 * this.loop3.sinNorm * this.loop3.cosNorm // set the radius
var c = `hsla(${280 + 60 * (this.loop3.cosNorm + this.offset) * this.loop2.sinNorm}, ${100}%, ${50 + 10 * this.loop3.sin}%, ${1})`
ctx.beginPath()
ctx.strokeStyle = c
ctx.lineCap = 'round'
ctx.lineWidth = r
var tx = x
var ty = y
for (var i = 0; i < Math.min(this.history_max * this.loop3.cosNorm, this.history.length); i++) {
ctx.moveTo(tx, ty)
tx = this.history[i][0]
ty = this.history[i][1]
ctx.lineTo(tx, ty)
}
ctx.stroke()
drawCircle(x, y, r * 2 + 3, c); // draw the circle
this.loop1.update() // update looper
this.loop2.update() // update looper
this.loop3.update() // update looper
this.history.unshift([x, y])
if (this.history.length > this.history_max) {
this.history.pop()
}
}
}
// initialize a set of particle
var particles = []
for (var i = 0; i < 90; i++) {
particles.push(new Particle())
}
function draw() {
// fill context with background color
fill(bg, 0.36)
// update all the particles
for (var i = 0; i < particles.length; i++) {
particles[i].draw() // do it once
}
// this is a draw loop, this will execute frequently and is comparable to EnterFrame on other platform
window.requestAnimationFrame(function() {
draw()
})
}
// start enterFrame loop
window.requestAnimationFrame(draw);
// force running setup
setup()
// re-setup canvas when the size of the window changes
window.addEventListener("resize", setup)
// create a class to hold value and have built in incrementing functionality
function Looper(steps, start) {
this.val = start || 0 // set value to start value if defined, or 1
this.steps = steps || 100 // set steps to passed value or default to 100
this.norm = this.val / this.range // initialize normalized value (between 0 and 1)
this.sin = Math.sin(this.norm * Math.PI * 2) // get sine value from norm normalized to [0, 2PI]
this.sinNorm = (this.sin + 1) / 2 // normalize sin to [0,1]
this.cos = Math.cos(this.norm * Math.PI * 2) // get cosine value from norm normalized to [0, 2PI]
this.cosNorm = (this.cos + 1) / 2 // normalize cos to [0,1]
this.update = function() {
this.val = (this.val + 1) % this.steps // update value
this.norm = this.val / this.steps // update normalize value (between 0 and 1)
this.sin = Math.sin(this.norm * Math.PI * 2) // get sine value from norm normalized to [0, 2PI]
this.sinNorm = (this.sin + 1) / 2 // normalize sine to [0,1]
this.cos = Math.cos(this.norm * Math.PI * 2) // get cosine value from norm normalized to [0, 2PI]
this.cosNorm = (this.cos + 1) / 2 // normalize cos to [0,1]
}
}
推荐阅读
- c# - 如何更改 RectTransform 的锚点以更改面板的宽度?
- angular - 如何使用 Angular Material 为特定日期启用/禁用 Angular 日期选择器?
- pandas - 在 Python 中使用 Pandas 提高处理大型 csv 文件的速度
- django - Permission.objects.get() 方法在 Django 中为单元测试创建测试数据库时不起作用
- soapui - 访问WADL下其他资源中的资源响应内容
- packer - 如何使用打包器 hcl 动态创建多个磁盘
- wcf - 在 WCF 的自定义属性中抛出自定义异常
- terraform - Terraform - 创建对象地图
- kubernetes - Kubernetes 在非默认命名空间中拉取镜像错误
- pandas - 从 Pandas 列创建具有相似日期的列表