docs(QRCode): Synchronize QR code demonstration and add SVG (#6660)

* fix: Synchronize QR code demonstration and add SVG

* fix: responsive loss and invalid border style

* docs: synchronize antd5.6.3 QRCode color in dark mode
pull/6697/head
selicens 2023-06-28 10:11:52 +08:00 committed by GitHub
parent 994707bd50
commit fc5181d1d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 195 additions and 21 deletions

View File

@ -265,3 +265,85 @@ export const QRCodeCanvas = defineComponent({
};
},
});
export const QRCodeSVG = defineComponent({
name: 'QRCodeSVG',
inheritAttrs: false,
props: {
...qrProps(),
color: String,
level: String,
bgColor: String,
fgColor: String,
marginSize: Number,
title: String,
},
setup(props) {
let cells = null;
let margin = null;
let numCells = null;
let calculatedImageSettings = null;
let fgPath = null;
let image = null;
watchEffect(() => {
const {
value,
size = DEFAULT_SIZE,
level = DEFAULT_LEVEL,
includeMargin = DEFAULT_INCLUDEMARGIN,
marginSize,
imageSettings,
} = props;
cells = qrcodegen.QrCode.encodeText(value, ERROR_LEVEL_MAP[level]).getModules();
margin = getMarginSize(includeMargin, marginSize);
numCells = cells.length + margin * 2;
calculatedImageSettings = getImageSettings(cells, size, margin, imageSettings);
if (imageSettings != null && calculatedImageSettings != null) {
if (calculatedImageSettings.excavation != null) {
cells = excavateModules(cells, calculatedImageSettings.excavation);
}
image = (
<image
xlinkHref={imageSettings.src}
height={calculatedImageSettings.h}
width={calculatedImageSettings.w}
x={calculatedImageSettings.x + margin}
y={calculatedImageSettings.y + margin}
preserveAspectRatio="none"
/>
);
}
// Drawing strategy: instead of a rect per module, we're going to create a
// single path for the dark modules and layer that on top of a light rect,
// for a total of 2 DOM nodes. We pay a bit more in string concat but that's
// way faster than DOM ops.
// For level 1, 441 nodes -> 2
// For level 40, 31329 -> 2
fgPath = generatePath(cells, margin);
});
return () => {
const bgColor = props.bgColor && DEFAULT_BGCOLOR;
const fgColor = props.fgColor && DEFAULT_FGCOLOR;
return (
<svg height={props.size} width={props.size} viewBox={`0 0 ${numCells} ${numCells}`}>
{!!props.title && <title>{props.title}</title>}
<path
fill={bgColor}
d={`M0,0 h${numCells}v${numCells}H0z`}
shape-rendering="crispEdges"
/>
<path fill={fgColor} d={fgPath} shape-rendering="crispEdges" />
{image}
</svg>
);
};
},
});

View File

@ -39,6 +39,29 @@ exports[`renders ./components/qrcode/demo/customSize.vue correctly 1`] = `
</div>
`;
exports[`renders ./components/qrcode/demo/customType.vue correctly 1`] = `
<div class="ant-space ant-space-horizontal ant-space-align-center">
<div class="ant-space-item" style="margin-right: 8px;">
<div style="width: 160px; height: 160px;" class="ant-qrcode">
<!----><canvas style="height: 134px; width: 134px;"></canvas>
<!---->
</div>
</div>
<!---->
<div class="ant-space-item">
<div style="width: 160px; height: 160px;" class="ant-qrcode">
<!----><svg height="134" width="134" viewBox="0 0 25 25">
<title></title>
<path fill="transparent" d="M0,0 h25v25H0z" shape-rendering="crispEdges"></path>
<path fill="#000" d="M0 0h7v1H0zM10 0h1v1H10zM13 0h2v1H13zM18,0 h7v1H18zM0 1h1v1H0zM6 1h1v1H6zM8 1h1v1H8zM11 1h1v1H11zM14 1h1v1H14zM18 1h1v1H18zM24,1 h1v1H24zM0 2h1v1H0zM2 2h3v1H2zM6 2h1v1H6zM9 2h2v1H9zM12 2h3v1H12zM18 2h1v1H18zM20 2h3v1H20zM24,2 h1v1H24zM0 3h1v1H0zM2 3h3v1H2zM6 3h1v1H6zM8 3h4v1H8zM13 3h1v1H13zM15 3h2v1H15zM18 3h1v1H18zM20 3h3v1H20zM24,3 h1v1H24zM0 4h1v1H0zM2 4h3v1H2zM6 4h1v1H6zM8 4h2v1H8zM11 4h4v1H11zM18 4h1v1H18zM20 4h3v1H20zM24,4 h1v1H24zM0 5h1v1H0zM6 5h1v1H6zM13 5h2v1H13zM16 5h1v1H16zM18 5h1v1H18zM24,5 h1v1H24zM0 6h7v1H0zM8 6h1v1H8zM10 6h1v1H10zM12 6h1v1H12zM14 6h1v1H14zM16 6h1v1H16zM18,6 h7v1H18zM8 7h1v1H8zM13 7h1v1H13zM15 7h2v1H15zM1 8h1v1H1zM3 8h4v1H3zM8 8h1v1H8zM10 8h1v1H10zM14 8h2v1H14zM17 8h2v1H17zM20 8h2v1H20zM23 8h1v1H23zM0 9h1v1H0zM3 9h1v1H3zM7 9h3v1H7zM11 9h1v1H11zM13 9h3v1H13zM17 9h1v1H17zM19 9h5v1H19zM0 10h1v1H0zM2 10h1v1H2zM5 10h2v1H5zM8 10h1v1H8zM11 10h1v1H11zM15 10h1v1H15zM18 10h2v1H18zM21 10h1v1H21zM24,10 h1v1H24zM1 11h1v1H1zM3 11h3v1H3zM7 11h2v1H7zM11 11h1v1H11zM14 11h1v1H14zM19 11h1v1H19zM21,11 h4v1H21zM1 12h4v1H1zM6 12h3v1H6zM11 12h8v1H11zM24,12 h1v1H24zM0 13h1v1H0zM3 13h1v1H3zM5 13h1v1H5zM7 13h1v1H7zM9 13h8v1H9zM20 13h1v1H20zM23 13h1v1H23zM0 14h2v1H0zM3 14h1v1H3zM5 14h2v1H5zM8 14h1v1H8zM13 14h5v1H13zM20,14 h5v1H20zM0 15h1v1H0zM2 15h3v1H2zM8 15h3v1H8zM12 15h3v1H12zM19 15h2v1H19zM22 15h1v1H22zM24,15 h1v1H24zM0 16h1v1H0zM5 16h2v1H5zM8 16h2v1H8zM11 16h1v1H11zM15 16h6v1H15zM22 16h2v1H22zM8 17h2v1H8zM12 17h5v1H12zM20 17h1v1H20zM23 17h1v1H23zM0 18h7v1H0zM10 18h1v1H10zM12 18h2v1H12zM16 18h1v1H16zM18 18h1v1H18zM20 18h2v1H20zM24,18 h1v1H24zM0 19h1v1H0zM6 19h1v1H6zM8 19h1v1H8zM11 19h1v1H11zM14 19h3v1H14zM20 19h1v1H20zM24,19 h1v1H24zM0 20h1v1H0zM2 20h3v1H2zM6 20h1v1H6zM8 20h2v1H8zM13 20h1v1H13zM15 20h7v1H15zM23,20 h2v1H23zM0 21h1v1H0zM2 21h3v1H2zM6 21h1v1H6zM8 21h2v1H8zM12 21h1v1H12zM14 21h1v1H14zM17 21h3v1H17zM21 21h1v1H21zM23,21 h2v1H23zM0 22h1v1H0zM2 22h3v1H2zM6 22h1v1H6zM9 22h2v1H9zM12 22h2v1H12zM16 22h2v1H16zM19 22h2v1H19zM22,22 h3v1H22zM0 23h1v1H0zM6 23h1v1H6zM8 23h3v1H8zM12 23h1v1H12zM14 23h1v1H14zM17 23h4v1H17zM22,23 h3v1H22zM0 24h7v1H0zM11 24h3v1H11zM16 24h1v1H16zM18 24h1v1H18zM21 24h1v1H21zM24,24 h1v1H24z" shape-rendering="crispEdges"></path>
<!---->
</svg>
</div>
</div>
<!---->
</div>
`;
exports[`renders ./components/qrcode/demo/download.vue correctly 1`] = `
<div style="width: 160px; height: 160px;" class="ant-qrcode">
<!----><canvas style="height: 134px; width: 134px;"></canvas>

View File

@ -15,5 +15,14 @@ Basic Usage.
</docs>
<template>
<a-qrcode value="https://www.antdv.com/" />
<a-space direction="vertical" align="center">
<a-qrcode :value="text" />
<a-input v-model:value="text" placeholder="-" :maxlength="60" />
</a-space>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const text = ref('https://www.antdv.com/');
</script>

View File

@ -16,7 +16,18 @@ Custom Color.
<template>
<a-space>
<div><a-qrcode value="http://www.antv.com" color="#73d13d" /></div>
<div><a-qrcode value="http://www.antv.com" color="#1677ff" /></div>
<a-qrcode value="http://www.antdv.com" :color="token.colorSuccessText" />
<a-qrcode
value="http://www.antdv.com"
:color="token.colorInfoText"
:bg-color="token.colorBgLayout"
/>
</a-space>
</template>
<script lang="ts" setup>
import { theme } from 'ant-design-vue';
const { useToken } = theme;
const { token } = useToken();
</script>

View File

@ -31,7 +31,7 @@ Custom Size.
:size="size"
:icon-size="size / 4"
error-level="H"
value="https://www.antv.com"
value="https://www.antdv.com"
icon="https://www.antdv.com/assets/logo.1ef800a8.svg"
/>
</template>

View File

@ -0,0 +1,22 @@
<docs>
---
order: 4
title:
zh-CN: 自定义渲染类型
en-US: Custom Render Type
---
## zh-CN
通过设置 `type` 自定义渲染结果提供 `canvas` `svg` 两个选项
## en-US
Customize the rendering results by `type`, provide options `canvas` and `svg`.
</docs>
<template>
<a-space>
<a-qrcode value="http://www.antdv.com" type="canvas" />
<a-qrcode value="http://www.antdv.com" type="svg" />
</a-space>
</template>

View File

@ -15,7 +15,7 @@ A way to download QRCode.
</docs>
<template>
<a-qrcode ref="qrcodeCanvasRef" value="http://www.antv.com" />
<a-qrcode ref="qrcodeCanvasRef" value="http://www.antdv.com" />
<br />
<br />
<a-button type="primary" @click="dowloadChange">Downlaod</a-button>

View File

@ -17,7 +17,7 @@ QRCode with Icon.
<template>
<a-qrcode
error-level="H"
value="https://www.antv.com"
value="https://www.antdv.com"
icon="https://www.antdv.com/assets/logo.1ef800a8.svg"
/>
</template>

View File

@ -3,6 +3,7 @@
<Base />
<Icon />
<Status />
<CustomType />
<CustomSize />
<CustomColor />
<Download />
@ -23,9 +24,20 @@ import CustomColor from './customColor.vue';
import Download from './download.vue';
import ErrorLevel from './errorLevel.vue';
import Popover from './popover.vue';
import CustomType from './customType.vue';
export default defineComponent({
components: { Base, Icon, Status, CustomSize, CustomColor, Download, ErrorLevel, Popover },
components: {
Base,
Icon,
Status,
CustomSize,
CustomColor,
Download,
ErrorLevel,
Popover,
CustomType,
},
category: 'Components',
subtitle: '二维码',
type: 'Data Display',

View File

@ -15,9 +15,9 @@ With Popover.
</docs>
<template>
<a-popover>
<a-popover :overlay-inner-style="{ padding: 0 }">
<template #content>
<a-qrcode value="http://www.antv.com" />
<a-qrcode value="http://www.antdv.com" :bordered="false" />
</template>
<img width="100" height="100" src="https://aliyuncdn.antdv.com/logo.png" />
</a-popover>

View File

@ -16,11 +16,11 @@ The status can be controlled by the value `status`.
<template>
<a-space>
<div><a-qrcode value="http://www.antv.com" status="loading" /></div>
<div><a-qrcode value="http://www.antv.com" status="expired" @refresh="refreshChange" /></div>
<a-qrcode value="http://www.antdv.com" status="loading" />
<a-qrcode
value="http://www.antdv.com"
status="expired"
@refresh="() => console.log('refresh')"
/>
</a-space>
</template>
<script lang="ts" setup>
const refreshChange = () => alert('updated');
</script>

View File

@ -15,10 +15,12 @@ Used when the link needs to be converted into a QR Code.
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| value | scanned link | string | - |
| type | render type | `'canvas'` \| `'svg'` | `canvas` |
| icon | include image url (only image link are supported) | string | - |
| size | QRCode size | number | 128 |
| iconSize | include image size | number | 32 |
| color | QRCode Color | string | `#000` |
| bgColor | QRCode Background Color | string | `transparent` |
| bordered | Whether has border style | boolean | `true` |
| errorLevel | Error Code Level | `'L'` \| `'M'` \| `'Q'` \| `'H'` | `'M'` |
| status | QRCode status | `active` \| `expired` \| `loading ` | `active` |

View File

@ -8,7 +8,7 @@ import Spin from '../spin';
import Button from '../button';
import { ReloadOutlined } from '@ant-design/icons-vue';
import { useToken } from '../theme/internal';
import { QRCodeCanvas } from './QRCodeCanvas';
import { QRCodeCanvas, QRCodeSVG } from './QRCode';
import warning from '../_util/warning';
import { qrcodeProps } from './interface';
@ -42,7 +42,8 @@ const QRCode = defineComponent({
icon = '',
size = 160,
iconSize = 40,
color = '#000',
color = token.value.colorText,
bgColor = 'transparent',
errorLevel = 'M',
} = props;
const imageSettings: QRCodeProps['imageSettings'] = {
@ -57,7 +58,7 @@ const QRCode = defineComponent({
value,
size: size - (token.value.paddingSM + token.value.lineWidth) * 2,
level: errorLevel,
bgColor: 'transparent',
bgColor,
fgColor: color,
imageSettings: icon ? imageSettings : undefined,
};
@ -69,13 +70,17 @@ const QRCode = defineComponent({
{...attrs}
style={[
attrs.style as CSSProperties,
{ width: props.size + 'px', height: props.size + 'px' },
{
width: `${props.size}px`,
height: `${props.size}px`,
backgroundColor: qrCodeProps.value.bgColor,
},
]}
class={[
hashId.value,
pre,
{
[`${prefixCls}-borderless`]: !props.bordered,
[`${pre}-borderless`]: !props.bordered,
},
]}
>
@ -96,7 +101,11 @@ const QRCode = defineComponent({
)}
</div>
)}
<QRCodeCanvas ref={qrCodeCanvas} {...qrCodeProps.value} />
{props.type === 'canvas' ? (
<QRCodeCanvas ref={qrCodeCanvas} {...qrCodeProps.value} />
) : (
<QRCodeSVG {...qrCodeProps.value} />
)}
</div>,
);
};

View File

@ -16,10 +16,12 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*M4PBTZ_n9OgAAA
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| value | 扫描后的地址 | string | - |
| type | 渲染类型 | `'canvas'` \| `'svg'` | `canvas` |
| icon | 二维码中图片的地址(目前只支持图片地址) | string | - |
| size | 二维码大小 | number | 160 |
| iconSize | 二维码中图片的大小 | number | 40 |
| color | 二维码颜色 | string | `#000` |
| bgColor | 二维码背景颜色 | string | `transparent` |
| bordered | 是否有边框 | boolean | `true` |
| errorLevel | 二维码纠错等级 | `'L'` \| `'M'` \| `'Q'` \| `'H'` | `'M'` |
| status | 二维码状态 | `active` \| `expired` \| `loading ` | `active` |

View File

@ -12,7 +12,9 @@ export const qrProps = () => {
return {
size: { type: Number, default: 160 },
value: { type: String, required: true },
type: stringType<'canvas' | 'svg'>('canvas'),
color: String,
bgColor: String,
includeMargin: Boolean,
imageSettings: objectType<ImageSettings>(),
};