Canvas Flip Image — Mirror and Flip Shapes on HTML5 Canvas
在 HTML5 Canvas 上翻转任意图片或形状——水平、垂直,或两者同时翻转。这种技术对于构建图片编辑器、设计工具以及基于 canvas 的应用程序至关重要,因为用户需要对内容进行镜像处理。
要使用 Konva 翻转任意节点,可以使用负的 scaleX 将其水平翻转,或使用 scaleY 将其垂直翻转。scale 属性相对于节点的原点生效。对于矩形来说,原点是左上角;对于圆形来说,原点是中心。你可以使用 offsetX 和 offsetY 更改原点——详见 Position vs Offset 指南。
根据你的使用场景,在翻转后你可能需要调整 {x, y},以保持节点在其原始位置。
说明:点击翻转按钮,查看形状如何水平和垂直镜像。
- Vanilla
- React
- Vue
import Konva from 'konva';
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
var layer = new Konva.Layer();
stage.add(layer);
var text1 = new Konva.Text({
x: 180,
y: 50,
text: '没有偏移的默认文本。它的原点在左上角。',
align: 'center',
width: 200,
});
layer.add(text1);
var text2 = new Konva.Text({
text: '原点在中心的文本',
width: 200,
align: 'center',
y: 100,
x: 270,
});
layer.add(text2);
// 将文本的水平原点设置在中心
text2.offsetX(text2.width() / 2);
var button = document.createElement('button');
button.innerText = '水平翻转';
button.style.position = 'absolute';
button.style.top = '5px';
button.style.left = '5px';
document.body.appendChild(button);
button.addEventListener('click', () => {
layer.find('Text').forEach((text) => {
text.to({
scaleX: -text.scaleX(),
});
});
});
import { Stage, Layer, Text } from 'react-konva';
import { useState, useRef } from 'react';
const App = () => {
const [texts, setTexts] = useState([
{
id: 1,
text: '没有偏移的默认文本。它的原点在左上角。',
x: 180,
y: 50,
width: 200,
align: 'center',
scaleX: 1,
offsetX: 0
},
{
id: 2,
text: '原点在中心的文本',
x: 270,
y: 100,
width: 200,
align: 'center',
scaleX: 1,
offsetX: 100 // 一半的宽度以居中
}
]);
const handleFlip = () => {
setTexts(texts.map(text => ({
...text,
scaleX: -text.scaleX
})));
};
return (
<div>
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
{texts.map((text) => (
<Text
key={text.id}
x={text.x}
y={text.y}
text={text.text}
width={text.width}
align={text.align}
scaleX={text.scaleX}
offsetX={text.offsetX}
/>
))}
</Layer>
</Stage>
<button
onClick={handleFlip}
style={{
position: 'absolute',
top: '5px',
left: '5px'
}}
>
水平翻转
</button>
</div>
);
};
export default App;
<template>
<div>
<v-stage :config="stageConfig">
<v-layer>
<v-text
v-for="text in texts"
:key="text.id"
:config="text"
/>
</v-layer>
</v-stage>
<button
@click="handleFlip"
style="position: absolute; top: 5px; left: 5px;"
>
水平翻转
</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const stageConfig = {
width: window.innerWidth,
height: window.innerHeight
};
const texts = ref([
{
id: 1,
text: '没有偏移的默认文本。它的原点在左上角。',
x: 180,
y: 50,
width: 200,
align: 'center',
scaleX: 1,
offsetX: 0
},
{
id: 2,
text: '原点在中心的文本',
x: 270,
y: 100,
width: 200,
align: 'center',
scaleX: 1,
offsetX: 100 // 一半的宽度以居中
}
]);
const handleFlip = () => {
texts.value = texts.value.map(text => ({
...text,
scaleX: -text.scaleX
}));
};
</script>