El autor ha creado un mapa mental web de código abierto . Recientemente, encontré un problema al optimizar el efecto de la imagen de fondo. Cuando se muestra en la página, la imagen de fondo se representa css
usando , pero cuando se exporta, en realidad está dibujado en la parte superior Entonces habrá un problema, la imagen de fondo de la imagen de fondo admite efectos más ricos, como configurar el tamaño, la posición y la repetición, pero el autor solo encontró un método y solo admite configurar la repetición efecto, así que cómo simular un cierto En cuanto al efecto de fondo, no se vaya, intentémoslo juntos a continuación.background-image
canvas
css
background-size
background-position
background-repeat
canvas
createPattern()
canvas
css
Lo primero que hay que explicar es que no simulará 100%
todos css
los efectos de forma perfecta y completa, porque es css
demasiado potente, la combinación de valores de los atributos es muy flexible, y hay muchos tipos, entre los que hay muchos tipos de unidades, por lo que solo se simularán algunas situaciones comunes y solo se considerarán px
unidades %
.
Después de leer este artículo, también puede revisar el canvas
método drawImage
y css
el uso de varios atributos establecidos en segundo plano.
El método drawImage() de canvas
En general, usaremos canvas
el drawImage()
método para dibujar la imagen de fondo. Echemos un vistazo a este método primero. Este método recibe más parámetros:
Solo se requieren tres parámetros.
Marco básico y herramientas.
La lógica central es cargar la imagen y luego usar drawImage
el método para dibujar la imagen, que no es más que parámetros css
calculados de acuerdo con varios atributos y valores drawImage
, por lo que se puede escribir el siguiente marco básico de la función:
const drawBackgroundImageToCanvas = (
ctx,// canvas绘图上下文
width,// canvas宽度
height,// canvas高度
img,// 图片url
{
backgroundSize, backgroundPosition, backgroundRepeat }// css样式,只模拟这三种
) => {
// canvas的宽高比
let canvasRatio = width / height
// 加载图片
let image = new Image()
image.src = img
image.onload = () => {
// 图片的宽高及宽高比
let imgWidth = image.width
let imgHeight = image.height
let imageRatio = imgWidth / imgHeight
// 绘制图片
// drawImage方法的参数值
let drawOpt = {
sx: 0,
sy: 0,
swidth: imgWidth,// 默认绘制完整图片
sheight: imgHeight,
x: 0,
y: 0,
width: imgWidth,// 默认不缩放图片
height: imgHeight
}
// 根据css属性和值计算...
// 绘制图片
ctx.drawImage(image, drawOpt.sx, drawOpt.sy, drawOpt.swidth, drawOpt.sheight, drawOpt.x, drawOpt.y, drawOpt.width, drawOpt.height)
}
}
A continuación, veamos algunas funciones de herramientas.
// 将以空格分隔的字符串值转换成成数字/单位/值数组
const getNumberValueFromStr = value => {
let arr = String(value).split(/\s+/)
return arr.map(item => {
if (/^[\d.]+/.test(item)) {
// 数字+单位
let res = /^([\d.]+)(.*)$/.exec(item)
return [Number(res[1]), res[2]]
} else {
// 单个值
return item
}
})
}
css
El valor del atributo es de tipo cadena o número, por ejemplo 100px 100% auto
, no es conveniente usarlo directamente, por lo que se convierte en [[100, 'px'], [100, '%'], 'auto']
un formulario.
// 缩放宽度
const zoomWidth = (ratio, height) => {
// w / height = ratio
return ratio * height
}
// 缩放高度
const zoomHeight = (ratio, width) => {
// width / h = ratio
return width / ratio
}
Calcule el ancho o alto escalado en función de la relación original y el nuevo ancho o alto.
Simular la propiedad de tamaño de fondo
background-repeat
El valor predeterminado es repeat
, no consideramos el caso de duplicación, así que configúrelo en no-repeat
.
background-size
El atributo se utiliza para establecer el tamaño de la imagen de fondo y puede aceptar cuatro tipos de valores, que se simulan a su vez.
tipo de longitud
Establezca la altura y el ancho de la imagen de fondo. El primer valor establece el ancho y el segundo establece la altura. Si solo se proporciona un valor, el segundo predeterminado es automático (automático).
css
El estilo es el siguiente:
.cssBox {
background-image: url('/1.jpg');
background-repeat: no-repeat;
background-size: 300px;
}
Si solo se establece un valor, representa el ancho real de la visualización de la imagen de fondo. Si no se establece la altura, se escalará automáticamente de acuerdo con la relación de aspecto de la imagen. El efecto es el siguiente:
La simulación es canvas
muy simple y se deben pasar cuatro parámetros al drawImage
método: img、x、y、width、height
, img
representando la imagen, x、y
representando la posición de colocar la imagen en el lienzo, no hay una configuración especial, obviamente, 0、0
representa width、height
acercar la imagen al especificado tamaño, si background-size
solo se pasa un valor, luego width
configúrelo directamente en este valor y height
calcule de acuerdo con la relación de aspecto de la imagen.Si se pasan dos valores, pase los dos valores por separado.Además width、height
, necesita para auto
procesar el valor, de la siguiente manera:
drawBackgroundImageToCanvas(ctx, width, height, this.img, {
backgroundSize: '300px'
})
const drawBackgroundImageToCanvas = () =>{
// ...
image.onload = () => {
// ...
// 模拟background-size
handleBackgroundSize({
backgroundSize,
drawOpt,
imageRatio
})
// ...
}
}
// 模拟background-size
const handleBackgroundSize = ({
backgroundSize, drawOpt, imageRatio }) => {
if (backgroundSize) {
// 将值转换成数组
let backgroundSizeValueArr = getNumberValueFromStr(backgroundSize)
// 两个值都为auto,那就相当于不设置
if (backgroundSizeValueArr[0] === 'auto' && backgroundSizeValueArr[1] === 'auto') {
return
}
// 图片宽度
let newNumberWidth = -1
if (backgroundSizeValueArr[0]) {
if (Array.isArray(backgroundSizeValueArr[0])) {
// 数字+单位类型
drawOpt.width = backgroundSizeValueArr[0][0]
newNumberWidth = backgroundSizeValueArr[0][0]
} else if (backgroundSizeValueArr[0] === 'auto') {
// auto类型,那么根据设置的新高度以图片原宽高比进行自适应
if (backgroundSizeValueArr[1]) {
drawOpt.width = zoomWidth(imageRatio, backgroundSizeValueArr[1][0])
}
}
}
// 设置了图片高度
if (backgroundSizeValueArr[1] && Array.isArray(backgroundSizeValueArr[1])) {
// 数字+单位类型
drawOpt.height = backgroundSizeValueArr[1][0]
} else if (newNumberWidth !== -1) {
// 没有设置图片高度或者设置为auto,那么根据设置的新宽度以图片原宽高比进行自适应
drawOpt.height = zoomHeight(imageRatio, newNumberWidth)
}
}
}
El efecto es el siguiente:
El efecto de establecer dos valores:
background-size: 300px 400px;
tipo de porcentaje
Se calculará el porcentaje del área localizada en relación con el fondo. El primer valor establece el porcentaje de ancho, el segundo valor establece el porcentaje de altura. Si solo se proporciona un valor, el segundo predeterminado es automático (automático). Por ejemplo, si está configurado 50% 80%
, significa que la imagen se escalará al 50%
ancho y 80%
alto del área de fondo.
css
El estilo es el siguiente:
.cssBox {
background-image: url('/1.jpg');
background-repeat: no-repeat;
background-size: 50% 80%;
}
La implementación también es muy simple. Sobre la base de lo anterior, juzgue si la unidad es %
, en caso afirmativo, canvas
calcule el ancho y el alto de la imagen que se mostrará de acuerdo con el ancho y el alto de la imagen. El segundo valor no está configurado. o es, auto
como antes, también se basa en la relación de aspecto de la imagen para adaptar.
drawBackgroundImageToCanvas(ctx, width, height, this.img, {
backgroundSize: '50% 80%'
})
handleBackgroundSize({
backgroundSize,
drawOpt,
imageRatio,
canvasWidth: width,// 传参新增canvas的宽高
canvasHeight: height
})
// 模拟background-size
const handleBackgroundSize = ({
backgroundSize, drawOpt, imageRatio, canvasWidth, canvasHeight }) => {
if (backgroundSize) {
// ...
// 图片宽度
let newNumberWidth = -1
if (backgroundSizeValueArr[0]) {
if (Array.isArray(backgroundSizeValueArr[0])) {
// 数字+单位类型
if (backgroundSizeValueArr[0][1] === '%') {
// %单位,则图片显示的高度为画布的百分之多少
drawOpt.width = backgroundSizeValueArr[0][0] / 100 * canvasWidth
newNumberWidth = drawOpt.width
} else {
// 其他都认为是px单位
drawOpt.width = backgroundSizeValueArr[0][0]
newNumberWidth = backgroundSizeValueArr[0][0]
}
} else if (backgroundSizeValueArr[0] === 'auto') {
// auto类型,那么根据设置的新高度以图片原宽高比进行自适应
if (backgroundSizeValueArr[1]) {
if (backgroundSizeValueArr[1][1] === '%') {
// 高度为%单位
drawOpt.width = zoomWidth(imageRatio, backgroundSizeValueArr[1][0] / 100 * canvasHeight)
} else {
// 其他都认为是px单位
drawOpt.width = zoomWidth(imageRatio, backgroundSizeValueArr[1][0])
}
}
}
}
// 设置了图片高度
if (backgroundSizeValueArr[1] && Array.isArray(backgroundSizeValueArr[1])) {
// 数字+单位类型
if (backgroundSizeValueArr[1][1] === '%') {
// 高度为%单位
drawOpt.height = backgroundSizeValueArr[1][0] / 100 * canvasHeight
} else {
// 其他都认为是px单位
drawOpt.height = backgroundSizeValueArr[1][0]
}
} else if (newNumberWidth !== -1) {
// 没有设置图片高度或者设置为auto,那么根据设置的新宽度以图片原宽高比进行自适应
drawOpt.height = zoomHeight(imageRatio, newNumberWidth)
}
}
}
El efecto es el siguiente:
tipo de cubierta
background-size
Configurado para significar que cover
la imagen mantendrá su relación de aspecto original y escalado al tamaño mínimo que cubrirá completamente el área de posicionamiento del fondo. Tenga en cuenta que la imagen no se deformará.
css
El estilo es el siguiente:
.cssBox {
background-image: url('/3.jpeg');
background-repeat: no-repeat;
background-size: cover;
}
Esta implementación también es muy simple.De acuerdo con la relación de aspecto de la imagen y la canvas
relación de aspecto de la imagen, ya sea que el ancho de la imagen ampliada sea canvas
el mismo que el ancho de la imagen, o que la altura de la imagen canvas
sea la misma que la altura de la imagen.
drawBackgroundImageToCanvas(ctx, width, height, this.img, {
backgroundSize: 'cover'
})
handleBackgroundSize({
backgroundSize,
drawOpt,
imageRatio,
canvasWidth: width,
canvasHeight: height,
canvasRatio// 参数增加canvas的宽高比
})
const handleBackgroundSize = ({
backgroundSize,
drawOpt,
imageRatio,
canvasWidth,
canvasHeight,
canvasRatio
}) => {
// ...
// 值为cover
if (backgroundSizeValueArr[0] === 'cover') {
if (imageRatio > canvasRatio) {
// 图片的宽高比大于canvas的宽高比,那么图片高度缩放到和canvas的高度一致,宽度自适应
drawOpt.height = canvasHeight
drawOpt.width = zoomWidth(imageRatio, canvasHeight)
} else {
// 否则图片宽度缩放到和canvas的宽度一致,高度自适应
drawOpt.width = canvasWidth
drawOpt.height = zoomHeight(imageRatio, canvasWidth)
}
return
}
// ...
}
El efecto es el siguiente:
contener tipo
background-size
Configurarlo en contain
tipo significa que la imagen aún mantendrá la relación de aspecto original y se escalará al tamaño máximo adecuado para el área de posicionamiento del fondo, es decir, la imagen se mostrará por completo, pero no necesariamente cubrirá el fondo. horizontal y verticalmente Puede haber espacios en blanco en una dirección.
css
estilo:
.cssBox {
background-image: url('/1.jpg');
background-repeat: no-repeat;
background-size: contain;
}
La implementación cover
es justo lo contrario de la implementación del tipo. Si la relación de aspecto de la imagen es mayor que la canvas
relación de aspecto de la imagen, para que la imagen se muestre completamente, el ancho de la imagen canvas
es consistente con el ancho de la imagen, y la altura es autoadaptativa.
const handleBackgroundSize = () => {
// ...
// 值为contain
if (backgroundSizeValueArr[0] === 'contain') {
if (imageRatio > canvasRatio) {
// 图片的宽高比大于canvas的宽高比,那么图片宽度缩放到和canvas的宽度一致,高度自适应
drawOpt.width = canvasWidth
drawOpt.height = zoomHeight(imageRatio, canvasWidth)
} else {
// 否则图片高度缩放到和canvas的高度一致,宽度自适应
drawOpt.height = canvasHeight
drawOpt.width = zoomWidth(imageRatio, canvasHeight)
}
return
}
}
El efecto es el siguiente:
background-size
La simulación aquí ha terminado, echemos un vistazo background-position
.
Simular la propiedad de posición de fondo
Primero mire background-size
la situación en la que no está configurado.
background-position
La propiedad se usa para establecer la posición inicial de la imagen de fondo, el valor predeterminado es 0% 0%
, también admite varios tipos diferentes de valores, véalos uno por uno.
tipo de porcentaje
El primer valor establece la posición horizontal y el segundo valor establece la posición vertical. La esquina superior izquierda es 0%0%
, la esquina inferior derecha es 100%100%
, si solo se establece un valor, el segundo valor predeterminado es 50%
, por ejemplo, se establece en 50% 60%
, lo que significa alinear 50% 60%
la posición de la imagen con la posición del área de fondo , y para ejemplo , que representa el punto central de la imagen y el centro de los puntos del área de fondo coinciden.50% 60%
50% 50%
css
estilo:
.cssBox {
background-image: url('/2.jpg');
background-repeat: no-repeat;
background-position: 50% 50%;
}
En términos de implementación, solo necesitamos usar los tres parámetros del drawImage
método . El ancho y el alto de la imagen no se escalarán, y la distancia correspondiente a la imagen se calcula de acuerdo con la proporción . Su diferencia es la posición de la imagen mostrada en la imagen.img
x、y
canvas
canvas
drawBackgroundImageToCanvas(ctx, width, height, this.img, {
backgroundPosition: '50% 50%'
})
const drawBackgroundImageToCanvas = () => {
// ...
// 模拟background-position
handleBackgroundPosition({
backgroundPosition,
drawOpt,
imgWidth,
imgHeight,
canvasWidth: width,
canvasHeight: height
})
// ...
}
// 模拟background-position
const handleBackgroundPosition = ({
backgroundPosition,
drawOpt,
imgWidth,
imgHeight,
canvasWidth,
canvasHeight
}) => {
if (backgroundPosition) {
// 将值转换成数组
let backgroundPositionValueArr = getNumberValueFromStr(backgroundPosition)
if (Array.isArray(backgroundPositionValueArr[0])) {
if (backgroundPositionValueArr.length === 1) {
// 如果只设置了一个值,第二个默认为50%
backgroundPositionValueArr.push([50, '%'])
}
// 水平位置
if (backgroundPositionValueArr[0][1] === '%') {
// 单位为%
let canvasX = (backgroundPositionValueArr[0][0] / 100) * canvasWidth
let imgX = (backgroundPositionValueArr[0][0] / 100) * imgWidth
// 计算差值
drawOpt.x = canvasX - imgX
}
// 垂直位置
if (backgroundPositionValueArr[1][1] === '%') {
// 单位为%
let canvasY = (backgroundPositionValueArr[1][0] / 100) * canvasHeight
let imgY = (backgroundPositionValueArr[1][0] / 100) * imgHeight
// 计算差值
drawOpt.y = canvasY - imgY
}
}
}
}
El efecto es el siguiente:
tipo de longitud
El primer valor representa la posición horizontal y el segundo valor representa la posición vertical. La esquina superior izquierda es 0 0
. La unidad puede ser px
o cualquier otra css
unidad, por supuesto, solo consideramos px
. Si solo se especifica un valor, los demás serán 50%
. Así que puedes mezclar %
y combinar px
.
css
estilo:
.cssBox {
background-image: url('/2.jpg');
background-repeat: no-repeat;
background-position: 50px 150px;
}
Esta implementación es más simple, simplemente pase el valor directamente al drawImage
parámetro x、y
.
drawBackgroundImageToCanvas(ctx, width, height, this.img, {
backgroundPosition: '50px 150px'
})
// 模拟background-position
const handleBackgroundPosition = ({
}) => {
// ...
// 水平位置
if (backgroundPositionValueArr[0][1] === '%') {
// ...
} else {
// 其他单位默认都为px
drawOpt.x = backgroundPositionValueArr[0][0]
}
// 垂直位置
if (backgroundPositionValueArr[1][1] === '%') {
// ...
} else {
// 其他单位默认都为px
drawOpt.y = backgroundPositionValueArr[1][0]
}
}
tipo de palabra clave
Eso es combinar palabras clave como , left
, y así sucesivamente. Se puede considerar como un valor especial, por lo que solo necesitamos escribir una asignación para asignar estas palabras clave a valores porcentuales.top
left top
center center
center bottom
%
.cssBox {
background-image: url('/2.jpg');
background-repeat: no-repeat;
background-position: right bottom;
}
drawBackgroundImageToCanvas(ctx, width, height, this.img, {
backgroundPosition: 'right bottom'
})
// 关键词到百分比值的映射
const keyWordToPercentageMap = {
left: 0,
top: 0,
center: 50,
bottom: 100,
right: 100
}
const handleBackgroundPosition = ({
}) => {
// ...
// 将关键词转为百分比
backgroundPositionValueArr = backgroundPositionValueArr.map(item => {
if (typeof item === 'string') {
return keyWordToPercentageMap[item] !== undefined
? [keyWordToPercentageMap[item], '%']
: item
}
return item
})
// ...
}
Combinado con tamaño de fondo
Finalmente, observamos background-size
lo que sucede cuando se combina con y .
.cssBox {
background-image: url('/2.jpg');
background-repeat: no-repeat;
background-size: cover;
background-position: right bottom;
}
drawBackgroundImageToCanvas(ctx, width, height, this.img, {
backgroundSize: 'cover',
backgroundPosition: 'right bottom'
})
El resultado es el siguiente:
Incoherente, ¿por qué es esto? Vamos a resolverlo. Primero, el procesamiento background-size
calculará drawImage
los parámetros width、height
, es decir, canvas
el ancho y el alto de la imagen que se muestra en él, y background-position
el ancho y el alto de la imagen se usarán en el procesamiento, pero lo que pasamos sigue siendo la imagen El ancho y alto original de , por supuesto hay un problema con este cálculo, modifíquelo:
// 模拟background-position
handleBackgroundPosition({
backgroundPosition,
drawOpt,
imgWidth: drawOpt.width,// 改为传计算后的图片的显示宽高
imgHeight: drawOpt.height,
imageRatio,
canvasWidth: width,
canvasHeight: height,
canvasRatio
})
Ahora mira el efecto de nuevo:
Simular la propiedad de repetición de fondo
background-repeat
El atributo se usa para establecer cómo colocar el objeto en mosaico background-image
. El valor predeterminado repeat
es, es decir, cuando la imagen es más pequeña que el área de fondo, se repetirá vertical y horizontalmente de forma predeterminada. Hay varios valores opcionales:
repeat-x
: solo la posición horizontal repetirá la imagen de fondorepeat-y
: Solo la posición vertical repetirá la imagen de fondono-repeat
:background-image
no repetiré
A continuación, implementamos estas situaciones.
sin repetición
En primer lugar, juzgue si el ancho y el alto de la imagen son más grandes que el área de fondo. Si es así, no hay necesidad de mosaico o procesamiento, y el otro valor no necesita no-repeat
ser procesado:
// 模拟background-repeat
handleBackgroundRepeat({
backgroundRepeat,
drawOpt,
imgWidth: drawOpt.width,
imgHeight: drawOpt.height,
imageRatio,
canvasWidth: width,
canvasHeight: height,
canvasRatio
})
Puede ver que el ancho y el alto de la imagen que cargamos aquí también es el background-size
ancho y el alto calculados para mostrar la imagen.
// 模拟background-repeat
const handleBackgroundRepeat = ({
backgroundRepeat,
drawOpt,
imgWidth,
imgHeight,
canvasWidth,
canvasHeight,
}) => {
if (backgroundRepeat) {
// 将值转换成数组
let backgroundRepeatValueArr = getNumberValueFromStr(backgroundRepeat)
// 不处理
if (backgroundRepeatValueArr[0] === 'no-repeat' || (imgWidth >= canvasWidth && imgHeight >= canvasHeight)) {
return
}
}
}
repetir-x
A continuación, agregue repeat-x
soporte para el par. Cuando canvas
el ancho sea mayor que el ancho de la imagen, se dibujará el mosaico horizontal y el dibujo llamará al drawImage
método repetidamente, por lo que es necesario pasar ctx
y image
parámetros al handleBackgroundRepeat
método. Además, si handleBackgroundRepeat
el dibujo se realiza en el método, el método de dibujo original No es necesario llamar:
// 模拟background-repeat
// 如果在handleBackgroundRepeat里进行了绘制,那么会返回true
let notNeedDraw = handleBackgroundRepeat({
ctx,
image,
...
})
if (!notNeedDraw) {
drawImage(ctx, image, drawOpt)
}
// 根据参数绘制图片
const drawImage = (ctx, image, drawOpt) => {
ctx.drawImage(
image,
drawOpt.sx,
drawOpt.sy,
drawOpt.swidth,
drawOpt.sheight,
drawOpt.x,
drawOpt.y,
drawOpt.width,
drawOpt.height
)
}
El método de dibujo se extrae en un método para facilitar su reutilización.
const handleBackgroundRepeat = ({
}) => {
// ...
// 水平平铺
if (backgroundRepeatValueArr[0] === 'repeat-x') {
if (canvasWidth > imgWidth) {
let x = 0
while (x < canvasWidth) {
drawImage(ctx, image, {
...drawOpt,
x
})
x += imgWidth
}
return true
}
}
// ...
}
Cada vez que x
se actualiza el parámetro de posición de ubicación de la imagen hasta que canvas
se excede el ancho.
repetir-y
El manejo correcto repeat-y
es similar:
const handleBackgroundRepeat = ({
}) => {
// ...
// 垂直平铺
if (backgroundRepeatValueArr[0] === 'repeat-y') {
if (canvasHeight > imgHeight) {
let y = 0
while (y < canvasHeight) {
drawImage(ctx, image, {
...drawOpt,
y
})
y += imgHeight
}
return true
}
}
// ...
}
repetir
Y por último repeat
el valor, que se repite tanto en horizontal como en vertical:
const handleBackgroundRepeat = ({
}) => {
// ...
// 平铺
if (backgroundRepeatValueArr[0] === 'repeat') {
let x = 0
while (x < canvasWidth) {
if (canvasHeight > imgHeight) {
let y = 0
while (y < canvasHeight) {
drawImage(ctx, image, {
...drawOpt,
x,
y
})
y += imgHeight
}
}
x += imgWidth
}
return true
}
}
De izquierda a derecha, se dibuja columna por columna, horizontalmente hasta el ancho x
sobrante canvas
y verticalmente hasta el alto y
sobrante .canvas
Combinación con tamaño de fondo, posición de fondo
Finalmente, mira la combinación con los dos primeros atributos.
css
estilo:
.cssBox {
background-image: url('/4.png');
background-repeat: repeat;
background-size: 50%;
background-position: 50% 50%;
}
El efecto es el siguiente:
El tamaño de la imagen es correcto, pero la posición es incorrecta. La css
mejor manera de hacerlo es background-position
colocar primero una imagen de acuerdo con el valor de y luego colocarla en mosaico, pero obviamente ignoramos esta situación y 0 0
comenzamos a dibujar desde la posición. cada vez.
Conociendo el principio, la solución también es muy sencilla, se handleBackgroundPosition
ha calculado en el método x、y
, es decir, la posición de colocación del primer cuadro antes del mosaico:
Solo necesitamos calcular cuántas imágenes se pueden colocar en mosaico a la izquierda y en la parte superior, y calcular la posición de la primera imagen en las direcciones horizontal y vertical como el x、y
valor inicial del ciclo siguiente.
const handleBackgroundRepeat = ({
}) => {
// 保存在handleBackgroundPosition中计算出来的x、y
let ox = drawOpt.x
let oy = drawOpt.y
// 计算ox和oy能平铺的图片数量
let oxRepeatNum = Math.ceil(ox / imgWidth)
let oyRepeatNum = Math.ceil(oy / imgHeight)
// 计算ox和oy第一张图片的位置
let oxRepeatX = ox - oxRepeatNum * imgWidth
let oxRepeatY = oy - oyRepeatNum * imgHeight
// 将oxRepeatX和oxRepeatY作为后续循环的x、y的初始值
// ...
// 平铺
if (backgroundRepeatValueArr[0] === 'repeat') {
let x = oxRepeatX
while (x < canvasWidth) {
if (canvasHeight > imgHeight) {
let y = oxRepeatY
// ...
}
}
}
}
fin
Este artículo simplemente se da cuenta de algunos de los efectos de los tres atributos canvas
simulados en , y El código fuente completo css
está en https://github.com/wanglin2/simulateCSSBackgroundInCanvas .background-size
background-position
background-repeat