当前位置: 首页 > news >正文

哪些网站做平面单页好看网架加工方案

哪些网站做平面单页好看,网架加工方案,建构网站,兰州产品营销网站建设APIs 参数说明类型默认值必传width水印的宽度,默认值为 content 自身的宽度numberundefinedfalseheight水印的高度,默认值为 content 自身的高度numberundefinedfalserotate水印绘制时,旋转的角度,单位 number-22falsezIndex追加…

APIs

参数说明类型默认值必传
width水印的宽度,默认值为 content 自身的宽度numberundefinedfalse
height水印的高度,默认值为 content 自身的高度numberundefinedfalse
rotate水印绘制时,旋转的角度,单位 °number-22false
zIndex追加的水印元素的 z-indexnumber9false
image图片源,建议使用 2 倍或 3 倍图,优先级高于文字stringundefinedfalse
content水印文字内容string | string[]‘’false
color字体颜色string‘rgba(0,0,0,.15)’false
fontSize字体大小,单位pxnumber16false
fontWeight字体粗细‘normal’ | ‘light’ | ‘weight’ | number‘normal’false
fontFamily字体类型string‘sans-serif’false
fontStyle字体样式‘none’ | ‘normal’ | ‘italic’ | ‘oblique’‘normal’false
gap水印之间的间距[number, number][100, 100]false
offset水印距离容器左上角的偏移量,默认为 gap/2[number, number][50, 50]false

效果如下图:在线预览

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建水印组件Watermark.vue

<script setup lang="ts">
import {unref,shallowRef,computed,watch,onMounted,onBeforeUnmount,nextTick,getCurrentInstance,getCurrentScope,onScopeDispose
} from 'vue'
import type { CSSProperties } from 'vue'
interface Props {width?: number // 水印的宽度,默认值为 content 自身的宽度height?: number // 水印的高度,默认值为 content 自身的高度rotate?: number // 水印绘制时,旋转的角度,单位 °zIndex?: number // 追加的水印元素的 z-indeximage?: string // 图片源,建议使用 2 倍或 3 倍图,优先级高于文字content?: string|string[] // 水印文字内容color?: string // 字体颜色fontSize?: number // 字体大小fontWeight?: 'normal'|'light'|'weight'|number // 	字体粗细fontFamily?: string // 字体类型fontStyle?: 'none'|'normal'|'italic'|'oblique' // 字体样式gap?: [number, number] // 水印之间的间距offset?: [number, number] // 水印距离容器左上角的偏移量,默认为 gap/2
}
const props = withDefaults(defineProps<Props>(), {width: undefined,height: undefined,rotate: -22,zIndex: 9,image: undefined,content: '',color: 'rgba(0,0,0,.15)',fontSize: 16,fontWeight: 'normal',fontFamily: 'sans-serif',fontStyle: 'normal',gap: () => [100, 100],offset: () => [50, 50]
})
/*** Base size of the canvas, 1 for parallel layout and 2 for alternate layout* Only alternate layout is currently supported*/
const BaseSize = 2
const FontGap = 3
// 和 ref() 不同,浅层 ref 的内部值将会原样存储和暴露,并且不会被深层递归地转为响应式。只有对 .value 的访问是响应式的。
const containerRef = shallowRef() // ref() 的浅层作用形式
const watermarkRef = shallowRef()
const stopObservation = shallowRef(false)
const gapX = computed(() => props.gap?.[0] ?? 100)
const gapY = computed(() => props.gap?.[1] ?? 100)
const gapXCenter = computed(() => gapX.value / 2)
const gapYCenter = computed(() => gapY.value / 2)
const offsetLeft = computed(() => props.offset?.[0] ?? gapXCenter.value)
const offsetTop = computed(() => props.offset?.[1] ?? gapYCenter.value)
const markStyle = computed(() => {const markStyle: CSSProperties = {zIndex: props.zIndex ?? 9,position: 'absolute',left: 0,top: 0,width: '100%',height: '100%',pointerEvents: 'none',backgroundRepeat: 'repeat'}/** Calculate the style of the offset */let positionLeft = offsetLeft.value - gapXCenter.valuelet positionTop = offsetTop.value - gapYCenter.valueif (positionLeft > 0) {markStyle.left = `${positionLeft}px`markStyle.width = `calc(100% - ${positionLeft}px)`positionLeft = 0}if (positionTop > 0) {markStyle.top = `${positionTop}px`markStyle.height = `calc(100% - ${positionTop}px)`positionTop = 0}markStyle.backgroundPosition = `${positionLeft}px ${positionTop}px`return markStyle
})
const destroyWatermark = () => {if (watermarkRef.value) {watermarkRef.value.remove()watermarkRef.value = undefined}
}
const appendWatermark = (base64Url: string, markWidth: number) => {if (containerRef.value && watermarkRef.value) {stopObservation.value = truewatermarkRef.value.setAttribute('style',getStyleStr({...markStyle.value,backgroundImage: `url('${base64Url}')`,backgroundSize: `${(gapX.value + markWidth) * BaseSize}px`}))containerRef.value?.append(watermarkRef.value)// Delayed executionsetTimeout(() => {stopObservation.value = false})}
}
// converting camel-cased strings to be lowercase and link it with Separato
function toLowercaseSeparator(key: string) {return key.replace(/([A-Z])/g, '-$1').toLowerCase()
}
function getStyleStr(style: CSSProperties): string {return Object.keys(style).map((key: any) => `${toLowercaseSeparator(key)}: ${style[key]};`).join(' ')
}
/*Get the width and height of the watermark. The default values are as followsImage: [120, 64]; Content: It's calculated by content
*/
const getMarkSize = (ctx: CanvasRenderingContext2D) => {let defaultWidth = 120let defaultHeight = 64const content = props.contentconst image = props.imageconst width = props.widthconst height = props.heightconst fontSize = props.fontSizeconst fontFamily = props.fontFamilyif (!image && ctx.measureText) {ctx.font = `${Number(fontSize)}px ${fontFamily}`const contents = Array.isArray(content) ? content : [content]const widths = contents.map(item => ctx.measureText(item!).width)defaultWidth = Math.ceil(Math.max(...widths))defaultHeight = Number(fontSize) * contents.length + (contents.length - 1) * FontGap}return [width ?? defaultWidth, height ?? defaultHeight] as const
}
// Returns the ratio of the device's physical pixel resolution to the css pixel resolution
function getPixelRatio () {return window.devicePixelRatio || 1
}
const fillTexts = (ctx: CanvasRenderingContext2D,drawX: number,drawY: number,drawWidth: number,drawHeight: number,
) => {const ratio = getPixelRatio()const content = props.contentconst fontSize = props.fontSizeconst fontWeight = props.fontWeightconst fontFamily = props.fontFamilyconst fontStyle = props.fontStyleconst color = props.colorconst mergedFontSize = Number(fontSize) * ratioctx.font = `${fontStyle} normal ${fontWeight} ${mergedFontSize}px/${drawHeight}px ${fontFamily}`ctx.fillStyle = colorctx.textAlign = 'center'ctx.textBaseline = 'top'ctx.translate(drawWidth / 2, 0)const contents = Array.isArray(content) ? content : [content]contents?.forEach((item, index) => {ctx.fillText(item ?? '', drawX, drawY + index * (mergedFontSize + FontGap * ratio))})
}
const renderWatermark = () => {const canvas = document.createElement('canvas')const ctx = canvas.getContext('2d')const image = props.imageconst rotate = props.rotate ?? -22if (ctx) {if (!watermarkRef.value) {watermarkRef.value = document.createElement('div')}const ratio = getPixelRatio()const [markWidth, markHeight] = getMarkSize(ctx)const canvasWidth = (gapX.value + markWidth) * ratioconst canvasHeight = (gapY.value + markHeight) * ratiocanvas.setAttribute('width', `${canvasWidth * BaseSize}px`)canvas.setAttribute('height', `${canvasHeight * BaseSize}px`)const drawX = (gapX.value * ratio) / 2const drawY = (gapY.value * ratio) / 2const drawWidth = markWidth * ratioconst drawHeight = markHeight * ratioconst rotateX = (drawWidth + gapX.value * ratio) / 2const rotateY = (drawHeight + gapY.value * ratio) / 2/** Alternate drawing parameters */const alternateDrawX = drawX + canvasWidthconst alternateDrawY = drawY + canvasHeightconst alternateRotateX = rotateX + canvasWidthconst alternateRotateY = rotateY + canvasHeightctx.save()rotateWatermark(ctx, rotateX, rotateY, rotate)if (image) {const img = new Image()img.onload = () => {ctx.drawImage(img, drawX, drawY, drawWidth, drawHeight)/** Draw interleaved pictures after rotation */ctx.restore()rotateWatermark(ctx, alternateRotateX, alternateRotateY, rotate)ctx.drawImage(img, alternateDrawX, alternateDrawY, drawWidth, drawHeight)appendWatermark(canvas.toDataURL(), markWidth)}img.crossOrigin = 'anonymous'img.referrerPolicy = 'no-referrer'img.src = image} else {fillTexts(ctx, drawX, drawY, drawWidth, drawHeight)/** Fill the interleaved text after rotation */ctx.restore()rotateWatermark(ctx, alternateRotateX, alternateRotateY, rotate)fillTexts(ctx, alternateDrawX, alternateDrawY, drawWidth, drawHeight)appendWatermark(canvas.toDataURL(), markWidth)}}
}
// Rotate with the watermark as the center point
function rotateWatermark(ctx: CanvasRenderingContext2D,rotateX: number,rotateY: number,rotate: number
) {ctx.translate(rotateX, rotateY)ctx.rotate((Math.PI / 180) * Number(rotate))ctx.translate(-rotateX, -rotateY)
}
onMounted(() => {renderWatermark()
})
watch(() => [props],() => {renderWatermark()},{deep: true, // 强制转成深层侦听器flush: 'post' // 在侦听器回调中访问被 Vue 更新之后的 DOM},
)
onBeforeUnmount(() => {destroyWatermark()
})
// Whether to re-render the watermark
const reRendering = (mutation: MutationRecord, watermarkElement?: HTMLElement) => {let flag = false// Whether to delete the watermark nodeif (mutation.removedNodes.length) {flag = Array.from(mutation.removedNodes).some(node => node === watermarkElement)}// Whether the watermark dom property value has been modifiedif (mutation.type === 'attributes' && mutation.target === watermarkElement) {flag = true}return flag
}
const onMutate = (mutations: MutationRecord[]) => {if (stopObservation.value) {return}mutations.forEach(mutation => {if (reRendering(mutation, watermarkRef.value)) {destroyWatermark()renderWatermark()}})
}
const defaultWindow = typeof window !== 'undefined' ? window : undefined
type Fn = () => void
function tryOnMounted(fn: Fn, sync = true) {if (getCurrentInstance()) onMounted(fn)else if (sync) fn()else nextTick(fn)
}
function useSupported(callback: () => unknown, sync = false) {const isSupported = shallowRef<boolean>()const update = () => (isSupported.value = Boolean(callback()))update()tryOnMounted(update, sync)return isSupported
}
function useMutationObserver(target: any,callback: MutationCallback,options: any,
) {const { window = defaultWindow, ...mutationOptions } = optionslet observer: MutationObserver | undefinedconst isSupported = useSupported(() => window && 'MutationObserver' in window)const cleanup = () => {if (observer) {observer.disconnect()observer = undefined}}const stopWatch = watch(() => unref(target),el => {cleanup()if (isSupported.value && window && el) {observer = new MutationObserver(callback)observer!.observe(el, mutationOptions)}},{ immediate: true })const stop = () => {cleanup()stopWatch()}tryOnScopeDispose(stop)return {isSupported,stop}
}
function tryOnScopeDispose(fn: Fn) {if (getCurrentScope()) {onScopeDispose(fn)return true}return false
}
useMutationObserver(containerRef, onMutate, {attributes: true // 观察所有监听的节点属性值的变化
})
</script>
<template><div ref="containerRef" style="position: relative;"><slot></slot></div>
</template>

在要使用的页面引入

<script setup lang="ts">
import Watermark from './Watermark.vue'
import { reactive } from 'vue'
const model = reactive({content: 'Vue Amazing UI',color: 'rgba(0,0,0,.15)',fontSize: 16,fontWeight: 400,zIndex: 9,rotate: -22,gap: [100, 100] as [number, number],offset: []
})
</script>
<template><div><h1>Watermark 水印</h1><h2 class="mt30 mb10">基本使用</h2><Watermark content="Vue Amazing UI"><div style="height: 360px" /></Watermark><h2 class="mt30 mb10">多行水印</h2><h3 class="mb10">通过 content 设置 字符串数组 指定多行文字水印内容。</h3><Watermark :content="['Vue Amazing UI', 'Hello World']"><div style="height: 400px" /></Watermark><h2 class="mt30 mb10">图片水印</h2><h3 class="mb10">通过 image 指定图片地址。为保证图片高清且不被拉伸,请设置 width 和 height, 并上传至少两倍的宽高的 logo 图片地址。</h3><Watermark:height="30":width="130"image="https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*lkAoRbywo0oAAAAAAAAAAAAADrJ8AQ/original"><div style="height: 360px" /></Watermark><h2 class="mt30 mb10">自定义配置</h2><h3 class="mb10">通过自定义参数配置预览水印效果。</h3><Flex><Watermark v-bind="model"><p class="u-paragraph">The light-speed iteration of the digital world makes products more complex. However, humanconsciousness and attention resources are limited. Facing this design contradiction, thepursuit of natural interaction will be the consistent direction of Ant Design.</p><p class="u-paragraph">Natural user cognition: According to cognitive psychology, about 80% of externalinformation is obtained through visual channels. The most important visual elements in theinterface design, including layout, colors, illustrations, icons, etc., should fullyabsorb the laws of nature, thereby reducing the user&apos;s cognitive cost and bringingauthentic and smooth feelings. In some scenarios, opportunely adding other sensorychannels such as hearing, touch can create a richer and more natural product experience.</p><p class="u-paragraph">Natural user behavior: In the interaction with the system, the designer should fullyunderstand the relationship between users, system roles, and task objectives, and alsocontextually organize system functions and services. At the same time, a series of methodssuch as behavior analysis, artificial intelligence and sensors could be applied to assistusers to make effective decisions and reduce extra operations of users, to saveusers&apos; mental and physical resources and make human-computer interaction morenatural.</p><imgstyle=" position: relative; z-index: 1; width: 100%; max-width: 800px;"src="https://cdn.jsdelivr.net/gh/themusecatcher/resources@0.0.3/6.jpg"alt="示例图片"/></Watermark><Flexstyle="width: 25%;flex-shrink: 0;border-left: 1px solid #eee;padding-left: 20px;margin-left: 20px;"verticalgap="middle"><p>Content</p><Input v-model:value="model.content" /><p>Color</p><Input v-model:value="model.color" /><p>FontSize</p><Slider v-model:value="model.fontSize" :step="1" :min="0" :max="100" /><p>FontWeight</p><InputNumber v-model:value="model.fontWeight" :step="100" :min="100" :max="1000" /><p>zIndex</p><Slider v-model:value="model.zIndex" :step="1" :min="0" :max="100" /><p>Rotate</p><Slider v-model:value="model.rotate" :step="1" :min="-180" :max="180" /><p>Gap</p><Space style="display: flex" align="baseline"><InputNumber v-model:value="model.gap[0]" placeholder="gapX" /><InputNumber v-model:value="model.gap[1]" placeholder="gapY" /></Space><p>Offset</p><Space style="display: flex" align="baseline"><InputNumber v-model:value="model.offset[0]" placeholder="offsetLeft" /><InputNumber v-model:value="model.offset[1]" placeholder="offsetTop" /></Space></Flex></Flex></div>
</template>
<style>
.u-paragraph {margin-bottom: 1em;color: rgba(0, 0, 0, .88);word-break: break-word;line-height: 1.5714285714285714;
}
</style>
http://www.yayakq.cn/news/888390/

相关文章:

  • 云南网站推广个人网站的类型
  • 哪些网站的做的好看的图片php做网站一般用什么软件
  • 新品发布会活动方案西安seo交流
  • 昭通网站开发大淘客网站开发
  • 北京网站seo费用专门做衣服特卖的网站
  • IT男网站建设怎么选wordpress模板
  • 深圳网络推广网站推广网站加密传输怎么做
  • 成都做网站多少钱建网站开发
  • 肇庆企业网站建设视频网站程序
  • 南沙营销网站建设做采购常用的几个网站
  • 做旅游网站的需求分析报告百度指数的主要用户是
  • 荥阳建设网站网站各页面
  • 精神文明地方联盟网站建设注册公司怎么注销
  • 青岛网站制作推广平台哈尔滨建设工程造价信息网
  • 建设机械网站精英洛阳建设厅网站
  • 食品加工设备建站方案泰坦科技网站建设
  • 找效果图的网站哪个好河南网站托管优化
  • 者珠海市建设局网站做销售网站
  • 贷款网站建设班级网站 建设目标
  • 替别人做设计的网站爬虫做视频网站
  • 电影宣传网站开发设计合肥做公司网站
  • 广州网站排名怎么优化网站建设多少钱一个
  • 医院门户网站模板html简单网页代码图片
  • 比较出名做耐克的网站上海外贸seo公司
  • 游戏开发 网站开发奎屯市网站
  • 乡土文化网站怎么做湖南响应式官网建设哪家好
  • 陕西百威建设监理有限司网站国外 电商网站
  • 网站的空间价格c 网站开发框架
  • 智能营销型网站wordpress子主题数量
  • 学做美食网站系部网站建设