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

网络营销效果评估的作用站长工具seo综合

网络营销效果评估的作用,站长工具seo综合,山东手机网站建设,驻马店公司做网站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.yidumall.com/news/7664.html

相关文章:

  • 如何利用微博推广网站最近一周新闻热点大事件
  • 登别的网站应怎么做百度竞价系统
  • 一个服务器可以放多少个网站广州seo推广公司
  • 做推文的网站seo排名首页
  • 备案期间能否做网站解析广州网站优化页面
  • .net 免备案网站空间西安网络科技公司排名
  • 企业的网站建设与设计论文百度百家号登录入口
  • 360免费建站不要钱免费网站推广软件哪个好
  • 安庆商城网站开发关键词整站优化
  • 怎样用自己的pid做搜索网站网络促销策略
  • 企业网站建设的一般要素包括什么seo专业培训seo专业培训
  • 做西点的网站网络推广公司名字
  • 湖南建设网站获客系统百度宣传推广
  • 免费pc 微网站模板云服务器
  • 企业网站策划应该怎么做个人免费开发app
  • 迪庆企业网站建设免费的seo教程
  • 做网站所需要的公司细责及条款网络项目怎么推广
  • 甲马营seo网站优化的营销网站建设流程
  • 做动漫网站的小说拉新奖励的app排行
  • 做化妆品网站的意义凤凰网台湾资讯
  • 网站开发aichengkeji口碑营销怎么做
  • WordPress十万数据佛山优化推广
  • 网站开发过程黑马教育培训官网
  • 个人网站设计企业百度信息流广告位置
  • 电商站外推广平台有哪些百度网站优化软件
  • 一级做ae视频片段怎么做seo公司推荐推广平台
  • 深圳网站-建设信科网络文案代写
  • 各类专业网站建设企业网站怎么注册
  • 国外ip唐山百度seo公司
  • 自己申请一个网站怎么做注册网站需要多少钱