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

网站建设的知识产权归属phpcms 笑话网站

网站建设的知识产权归属,phpcms 笑话网站,创意中山网站建设,网站提交自动秒收录文章目录 1、创建海报的基本逻辑2、用canvas绘制文字3、绘制矩形4、绘制圆形5、绘制圆角矩形6、绘制图片7、执行绘制8、完整的代码 1、创建海报的基本逻辑 1、先创建dom元素 wrapperHeight是根据海报的内容计算出来海报的高度 view classpreview-card-wrap ta… 文章目录 1、创建海报的基本逻辑2、用canvas绘制文字3、绘制矩形4、绘制圆形5、绘制圆角矩形6、绘制图片7、执行绘制8、完整的代码 1、创建海报的基本逻辑 1、先创建dom元素 wrapperHeight是根据海报的内容计算出来海报的高度 view classpreview-card-wrap tap.stopview classposter-box :class{ show: isDrew }canvasidmyCanvascanvas-idmyCanvas:style{width: 750rpx,height: wrapperHeight rpx,}/canvas/view/view2、创建海报类 class Poster {canvasId: string;instanceComponent: ReturnTypetypeof getCurrentInstance | undefined;ctx: UniApp.CanvasContext | undefined undefined;width 0;height 0;isPixel: boolean;drawSteps: DrawSteps [];constructor(canvasId: string,instance?: ReturnTypetypeof getCurrentInstance,{ isPixel true } InitConfig{}) {this.canvasId canvasId;this.instanceComponent instance;this.ctx uni.createCanvasContext(canvasId, instance);this.isPixel isPixel;}/*** 设置画布大小* param width 画布宽度* param height 画布高度*/public setCanvasSize(width: number, height: number) {this.width width;this.height height;}/*** 清空画布*/clearAll() {this.ctx?.clearRect(0,0,this.getPixel(this.width),this.getPixel(this.height));// clearRect() 方法只是将指定区域的像素设置为透明但不会直接触发画布的重新绘制。// 因此需要在清除画布后显式调用 draw() 方法才能使清除的效果立即生效即将空白画布展示在页面上。// 这个方法只是为了更新画布this.ctx?.draw();} }export default Poster; 3、创建海报类 import { getCurrentInstance, ref } from vue;const poster refPoster | undefined | any(undefined);poster.value new Poster(myCanvas, self, { isPixel: false });const self getCurrentInstance(); // 设置画布大小 poster.value.setCanvasSize(750, wrapperHeight.value); // 绘制前先清空画布 poster.value.clearAll();2、用canvas绘制文字 先将px和rpx进行转换 /*** 获取大小* param size*/getPixel(size: number) {return this.isPixel ? size : rpx2px(size);}获取文字的宽度 /*** 获取文字宽度* param text 文字* param fontStyle 字体样式同 css 的 font 属性* returns {number} 文字宽度*/public getTextWidth(text: string, fontStyle?: string) {if (!this.ctx || !text.trim()) return 0;this.ctx.save();this.ctx.font fontStyle || 14px sans-serif;const dimension this.ctx.measureText(text);this.ctx.restore();return this.isPixel ? dimension.width : px2rpx(dimension.width);}给文字加上省略号 // 给文字加上省略号public correctEllipsisText(text: string, width: number, fontStyle?: string) {let resultText ;const strSplits text.split();while (strSplits.length 0) {const s strSplits.shift();const isGtWidth this.getPixel(this.getTextWidth(resultText s, fontStyle)) this.getPixel(width);if (isGtWidth) {resultText resultText.substring(0, resultText.length) ...;break;}resultText s;}return resultText;}绘制文字的逻辑 /*** 绘制文字* param text 文字* param x 横向绘制点* param y 纵向绘制点* param maxWidth 绘制区域最大宽度文字宽度超过则换行* param color 文字颜色* param fontSize 文字大小* param fontWeight 文字粗细* param borderWidth 文字描边粗细* param borderColor 文字描边样式* param lineHeight 行高即文字行与行之间的间距* param UseEllipsis 当超出文字宽度是否使用省略号*/public async drawText({text,x,y,maxWidth,color,fontSize,fontFamily,fontWeight 500,borderWidth,borderColor,lineHeight 1.2,UseEllipsis true,}: TextDrawStep) {if (!this.ctx) return;const fontStyle ${fontWeight} ${fontSize ? this.getPixel(fontSize) : 14}px ${${fontFamily} || sans-serif};this.ctx.save();this.ctx.setTextBaseline(top);this.ctx.font fontStyle;color (this.ctx.fillStyle color);if (borderColor) this.ctx.strokeStyle borderColor;// 绘制文字边框样式if (borderWidth) {this.ctx.lineWidth borderWidth;}if (UseEllipsis) {// 将超出canvas宽度的文字用...展示const drawText this.correctEllipsisText(text,maxWidth || this.width,fontStyle);if (borderWidth) {this.ctx.strokeText(drawText,this.getPixel(x),this.getPixel(y),maxWidth ? this.getPixel(maxWidth) : maxWidth);}this.ctx.fillText(drawText,this.getPixel(x),this.getPixel(y),maxWidth ? this.getPixel(maxWidth) : maxWidth);} else {// 将文本分割成数组const words text.split();let line ; // 当前行的文字内容let yPos y; // 当前行的纵坐标位置for (let i 0; i words.length; i) {const testLine line words[i]; // 当前行加上当前单词// 测量当前行的宽度const textWidth this.getTextWidth(testLine, fontStyle);// 如果当前行的宽度超过最大的宽度 需要换行if (textWidth this.getPixel(maxWidth || this.width)) {// 讲当前行绘制到canvas上if (borderWidth) {this.ctx.strokeText(line,this.getPixel(x),this.getPixel(y),maxWidth ? this.getPixel(maxWidth) : maxWidth);this.ctx.fillText(line,this.getPixel(x),this.getPixel(yPos),maxWidth ? this.getPixel(maxWidth) : maxWidth);// 开始新一行yPos lineHeight * (fontSize ? this.getPixel(fontSize) : 14);} else {line testLine;}}}this.ctx.strokeText(line, this.getPixel(x), this.getPixel(y));this.ctx.fillText(line, this.getPixel(x), this.getPixel(yPos));}this.ctx.restore();}3、绘制矩形 /*** 绘制直边形状* param lines 坐标数组第一个为设置落笔点坐标数组最后一个如果和第一个一样可省略* param fillColor 填充颜色*/public drawLineShape({ lines, fillColor }: LineShapeDrawStep) {if (!this.ctx || !lines.length) return;this.ctx.save();// 开始绘制路径this.ctx.beginPath();const [x, y] lines[0];this.ctx.moveTo(this.getPixel(x), this.getPixel(y));// 遍历坐标数组绘制直线段for (let i 1; i lines.length; i) {const [ix, iy] lines[i];this.ctx.lineTo(this.getPixel(ix), this.getPixel(iy));}if (this.ctx fillColor) {this.ctx.fillStyle fillColor;this.ctx.fill();} else {this.ctx.closePath();}this.ctx.restore();}4、绘制圆形 /*** 绘制圆形*/public drawCircleShape({x,y,radius,startAngle,endAngle,anticlockwise,fillColor,}: CircleShapeDrawStep) {if (!this.ctx) return;this.ctx.save();this.ctx.beginPath();this.ctx.arc(this.getPixel(x),this.getPixel(y),this.getPixel(radius),this.getPixel(startAngle),this.getPixel(endAngle),anticlockwise);if (this.ctx fillColor) {this.ctx.setFillStyle(fillColor);this.ctx.fill();} else {this.ctx.closePath();}this.ctx.restore();}5、绘制圆角矩形 /*** 绘制圆角矩形* param x x坐标* param y y坐标* param width 宽度* param height 高度* param radius 圆角半径* param fillColor 填充颜色*/public roundRect ({x,y,width,height,radius,fillColor,}: roundRectShapeDrawStep) {if (!this.ctx) return;const dx this.getPixel(x);const dy this.getPixel(y);const dRadius this.getPixel(radius);const dWidth this.getPixel(width);const dHeight this.getPixel(height);this.ctx.beginPath();this.ctx.moveTo(dx dRadius, dy);// 下面三个点形成切线来画出圆弧this.ctx.lineTo(dx dWidth - dRadius, dy);this.ctx.arcTo(dx dWidth, dy, dx dWidth, dy dRadius, dRadius);this.ctx.lineTo(dx dWidth, dy dHeight - dRadius);this.ctx.arcTo(dx dWidth,dy dHeight,dx dWidth - dRadius,dy dHeight,dRadius);this.ctx.lineTo(dx dRadius, dy dHeight);this.ctx.arcTo(dx, dy dHeight, dx, dy dHeight - dRadius, dRadius);this.ctx.lineTo(dx, dy dRadius);this.ctx.arcTo(dx, dy, dx dRadius, dy, dRadius);this.ctx.closePath();this.ctx.fillStyle fillColor;this.ctx.fill();};6、绘制图片 /*** 绘制图片* param image 图片路径必须为本地路径或临时路径* param x 横向绘制点* param y 纵向绘制点* param width 绘制宽度* param height 绘制高度* param isCircle 是否为圆形图, 宽高需相等*/public async drawImage({image,x,y,width,height,isCircle false,clipConfig,}: ImageDrawStep) {if (!this.ctx) return;this.ctx.save();if (isCircle) {const r Math.floor(this.getPixel(width) / 2);// context.arc(x, y, radius, startAngle, endAngle, anticlockwise);this.ctx.arc(this.getPixel(x) r,this.getPixel(y) r,r,0,2 * Math.PI);// 只有在剪切路径范围内的内容才会被保留超出剪切路径范围的部分会被裁剪掉。this.ctx.clip();}await sleep(50);let clipParams: number[] [];if (clipConfig) {clipParams [clipConfig.x,clipConfig.y,clipConfig.width,clipConfig.height,];}this.ctx.drawImage(image,...clipParams,this.getPixel(x),this.getPixel(y),this.getPixel(width),this.getPixel(height));// console.log(this.ctx, 查看图片的上下文);this.ctx.restore();}7、执行绘制 /*** 执行绘制*/async draw(callback?: Function) {// 初始化绘图步骤数组的索引let index 0;// 循环遍历绘图步骤数组while (index this.drawSteps.length) {// 从当前绘图步骤中提取出类型和其他属性const { type, ...otherProps } DrawStepthis.drawSteps[index];const stepProps AnyObjectotherProps;const props AnyObject{};// 合并其他属性到 props 中Object.assign(props,stepProps.getProps? await stepProps.getProps(this.drawSteps, index): stepProps);// this.drawSteps[index].drawData {// ...props,// ...(this.drawSteps[index].drawData || {}),// };// 根据类型执行相应的绘图操作if (type DrawType.Text) {await this.drawText(TextDrawStepprops);} else if (type DrawType.Image) {await this.drawImage(ImageDrawStepprops);} else if (type DrawType.LineShape) {await this.drawLineShape(LineShapeDrawStepprops);} else if (type DrawType.CircleShape) {await this.drawCircleShape(CircleShapeDrawStepprops);} else if (type DrawType.RoundRectShape) {await this.roundRect(roundRectShapeDrawStepprops);}// 如果当前绘图步骤需要立即绘制则执行绘图同步操作props.immediateDraw (await this.syncDraw());// 移动到下一个绘图步骤index 1;}// 执行最终的绘图操作并在绘制完成后执行回调函数this.ctx?.draw(true, (res) {callback?.(res);});}8、完整的代码 import type { getCurrentInstance } from vue; import { px2rpx, rpx2px } from /utils/view; import type {DrawStep,DrawSteps,ImageDrawStep,InitConfig,LineShapeDrawStep,TextDrawStep,CircleShapeDrawStep,roundRectShapeDrawStep, } from ./poster; import { DrawType } from ./poster; import { sleep } from /utils;class Poster {canvasId: string;instanceComponent: ReturnTypetypeof getCurrentInstance | undefined;ctx: UniApp.CanvasContext | undefined undefined;width 0;height 0;isPixel: boolean;drawSteps: DrawSteps [];constructor(canvasId: string,instance?: ReturnTypetypeof getCurrentInstance,{ isPixel true } InitConfig{}) {this.canvasId canvasId;this.instanceComponent instance;this.ctx uni.createCanvasContext(canvasId, instance);this.isPixel isPixel;}/*** 获取大小* param size*/getPixel(size: number) {return this.isPixel ? size : rpx2px(size);}public getCanvasSize() {return {width: this.width,height: this.height,};}/*** 设置画布大小* param width 画布宽度* param height 画布高度*/public setCanvasSize(width: number, height: number) {this.width width;this.height height;}/*** 获取文字宽度* param text 文字* param fontStyle 字体样式同 css 的 font 属性* returns {number} 文字宽度*/public getTextWidth(text: string, fontStyle?: string) {if (!this.ctx || !text.trim()) return 0;this.ctx.save();this.ctx.font fontStyle || 14px sans-serif;const dimension this.ctx.measureText(text);this.ctx.restore();return this.isPixel ? dimension.width : px2rpx(dimension.width);}// 给文字加上省略号public correctEllipsisText(text: string, width: number, fontStyle?: string) {let resultText ;const strSplits text.split();while (strSplits.length 0) {const s strSplits.shift();const isGtWidth this.getPixel(this.getTextWidth(resultText s, fontStyle)) this.getPixel(width);if (isGtWidth) {resultText resultText.substring(0, resultText.length) ...;break;}resultText s;}return resultText;}/*** 绘制图片* param image 图片路径必须为本地路径或临时路径* param x 横向绘制点* param y 纵向绘制点* param width 绘制宽度* param height 绘制高度* param isCircle 是否为圆形图, 宽高需相等*/public async drawImage({image,x,y,width,height,isCircle false,clipConfig,}: ImageDrawStep) {if (!this.ctx) return;this.ctx.save();if (isCircle) {const r Math.floor(this.getPixel(width) / 2);// context.arc(x, y, radius, startAngle, endAngle, anticlockwise);this.ctx.arc(this.getPixel(x) r,this.getPixel(y) r,r,0,2 * Math.PI);// 只有在剪切路径范围内的内容才会被保留超出剪切路径范围的部分会被裁剪掉。this.ctx.clip();}await sleep(50);let clipParams: number[] [];if (clipConfig) {clipParams [clipConfig.x,clipConfig.y,clipConfig.width,clipConfig.height,];}this.ctx.drawImage(image,...clipParams,this.getPixel(x),this.getPixel(y),this.getPixel(width),this.getPixel(height));// console.log(this.ctx, 查看图片的上下文);this.ctx.restore();}/*** 绘制文字* param text 文字* param x 横向绘制点* param y 纵向绘制点* param maxWidth 绘制区域最大宽度文字宽度超过则换行* param color 文字颜色* param fontSize 文字大小* param fontWeight 文字粗细* param borderWidth 文字描边粗细* param borderColor 文字描边样式* param lineHeight 行高即文字行与行之间的间距* param UseEllipsis 当超出文字宽度是否使用省略号*/public async drawText({text,x,y,maxWidth,color,fontSize,fontFamily,fontWeight 500,borderWidth,borderColor,lineHeight 1.2,UseEllipsis true,}: TextDrawStep) {if (!this.ctx) return;const fontStyle ${fontWeight} ${fontSize ? this.getPixel(fontSize) : 14}px ${${fontFamily} || sans-serif};this.ctx.save();this.ctx.setTextBaseline(top);this.ctx.font fontStyle;color (this.ctx.fillStyle color);if (borderColor) this.ctx.strokeStyle borderColor;// 绘制文字边框样式if (borderWidth) {this.ctx.lineWidth borderWidth;}if (UseEllipsis) {// 将超出canvas宽度的文字用...展示const drawText this.correctEllipsisText(text,maxWidth || this.width,fontStyle);if (borderWidth) {this.ctx.strokeText(drawText,this.getPixel(x),this.getPixel(y),maxWidth ? this.getPixel(maxWidth) : maxWidth);}this.ctx.fillText(drawText,this.getPixel(x),this.getPixel(y),maxWidth ? this.getPixel(maxWidth) : maxWidth);} else {// 将文本分割成数组const words text.split();let line ; // 当前行的文字内容let yPos y; // 当前行的纵坐标位置for (let i 0; i words.length; i) {const testLine line words[i]; // 当前行加上当前单词// 测量当前行的宽度const textWidth this.getTextWidth(testLine, fontStyle);// 如果当前行的宽度超过最大的宽度 需要换行if (textWidth this.getPixel(maxWidth || this.width)) {// 讲当前行绘制到canvas上if (borderWidth) {this.ctx.strokeText(line,this.getPixel(x),this.getPixel(y),maxWidth ? this.getPixel(maxWidth) : maxWidth);this.ctx.fillText(line,this.getPixel(x),this.getPixel(yPos),maxWidth ? this.getPixel(maxWidth) : maxWidth);// 开始新一行yPos lineHeight * (fontSize ? this.getPixel(fontSize) : 14);} else {line testLine;}}}this.ctx.strokeText(line, this.getPixel(x), this.getPixel(y));this.ctx.fillText(line, this.getPixel(x), this.getPixel(yPos));}this.ctx.restore();}/*** 绘制直边形状* param lines 坐标数组第一个为设置落笔点坐标数组最后一个如果和第一个一样可省略* param fillColor 填充颜色*/public drawLineShape({ lines, fillColor, gradients }: LineShapeDrawStep) {if (!this.ctx || !lines.length) return;this.ctx.save();this.ctx.beginPath();const [x, y] lines[0];this.ctx.moveTo(this.getPixel(x), this.getPixel(y));for (let i 1; i lines.length; i) {const [ix, iy] lines[i];this.ctx.lineTo(this.getPixel(ix), this.getPixel(iy));}if (this.ctx fillColor) {this.ctx.fillStyle fillColor;this.ctx.fill();} else if (this.ctx gradients?.length) {var lineargradient this.ctx.createLinearGradient(gradients[0],gradients[1],gradients[2],gradients[3]);lineargradient.addColorStop(0, #363636);lineargradient.addColorStop(1, white);this.ctx.setFillStyle(lineargradient);this.ctx.fill();} else {this.ctx.closePath();}this.ctx.restore();}/*** 绘制圆形*/public drawCircleShape({x,y,radius,startAngle,endAngle,anticlockwise,fillColor,}: CircleShapeDrawStep) {if (!this.ctx) return;this.ctx.save();this.ctx.beginPath();this.ctx.arc(this.getPixel(x),this.getPixel(y),this.getPixel(radius),this.getPixel(startAngle),this.getPixel(endAngle),anticlockwise);if (this.ctx fillColor) {this.ctx.setFillStyle(fillColor);this.ctx.fill();} else {this.ctx.closePath();}this.ctx.restore();}syncDraw(): Promisevoid {return new Promise((resolve) {this.ctx?.draw(true, async () {await sleep(30);resolve();});});}/*** 绘制圆角矩形* param x x坐标* param y y坐标* param width 宽度* param height 高度* param radius 圆角半径* param fillColor 填充颜色*/public roundRect ({x,y,width,height,radius,fillColor,}: roundRectShapeDrawStep) {if (!this.ctx) return;const dx this.getPixel(x);const dy this.getPixel(y);const dRadius this.getPixel(radius);const dWidth this.getPixel(width);const dHeight this.getPixel(height);this.ctx.beginPath();this.ctx.moveTo(dx dRadius, dy);// 下面三个点形成切线来画出圆弧this.ctx.lineTo(dx dWidth - dRadius, dy);this.ctx.arcTo(dx dWidth, dy, dx dWidth, dy dRadius, dRadius);this.ctx.lineTo(dx dWidth, dy dHeight - dRadius);this.ctx.arcTo(dx dWidth,dy dHeight,dx dWidth - dRadius,dy dHeight,dRadius);this.ctx.lineTo(dx dRadius, dy dHeight);this.ctx.arcTo(dx, dy dHeight, dx, dy dHeight - dRadius, dRadius);this.ctx.lineTo(dx, dy dRadius);this.ctx.arcTo(dx, dy, dx dRadius, dy, dRadius);this.ctx.closePath();this.ctx.fillStyle fillColor;this.ctx.fill();};/*** 执行绘制*/async draw(callback?: Function) {// 初始化绘图步骤数组的索引let index 0;// 循环遍历绘图步骤数组while (index this.drawSteps.length) {// 从当前绘图步骤中提取出类型和其他属性const { type, ...otherProps } DrawStepthis.drawSteps[index];const stepProps AnyObjectotherProps;const props AnyObject{};// 合并其他属性到 props 中Object.assign(props,stepProps.getProps? await stepProps.getProps(this.drawSteps, index): stepProps);// this.drawSteps[index].drawData {// ...props,// ...(this.drawSteps[index].drawData || {}),// };// 根据类型执行相应的绘图操作if (type DrawType.Text) {await this.drawText(TextDrawStepprops);} else if (type DrawType.Image) {await this.drawImage(ImageDrawStepprops);} else if (type DrawType.LineShape) {await this.drawLineShape(LineShapeDrawStepprops);} else if (type DrawType.CircleShape) {await this.drawCircleShape(CircleShapeDrawStepprops);} else if (type DrawType.RoundRectShape) {await this.roundRect(roundRectShapeDrawStepprops);}// 如果当前绘图步骤需要立即绘制则执行绘图同步操作props.immediateDraw (await this.syncDraw());// 移动到下一个绘图步骤index 1;}// 执行最终的绘图操作并在绘制完成后执行回调函数this.ctx?.draw(true, (res) {callback?.(res);});}/*** 将绘制内容转成图片* returns {Promisestring} 图片临时路径*/canvas2Image(): PromiseUniApp.CanvasToTempFilePathRes | undefined {if (!this.ctx) return;return new Promise((resolve) {uni.canvasToTempFilePath({canvasId: this.canvasId,x: 0,y: 0,width: this.width,height: this.height,success: resolve,},this.instanceComponent);});}/*** 清空画布*/clearAll() {this.ctx?.clearRect(0,0,this.getPixel(this.width),this.getPixel(this.height));// clearRect() 方法只是将指定区域的像素设置为透明但不会直接触发画布的重新绘制。// 因此需要在清除画布后显式调用 draw() 方法才能使清除的效果立即生效即将空白画布展示在页面上。// 这个方法只是为了更新画布this.ctx?.draw();} }export default Poster; export enum DrawType {Text text,Image image,LineShape lineShape,CircleShape circleShape,RoundRectShape roundRectShape, }export interface InitConfig {isPixel: boolean; }export type BaseDrawStep {x: number;y: number; };export type GetPropsO {getProps: (steps: DrawSteps, index: number) O | PromiseO; };export type TextDrawStep BaseDrawStep {text: string;maxWidth?: number;color?: string;fontSize?: number;fontFamily?: string;fontWeight?: number;borderWidth?: number;borderColor?: string;lineHeight?: number;UseEllipsis?: boolean; };export type ImageDrawStep BaseDrawStep {image: string;width: number;height: number;isCircle?: boolean;clipConfig?: {x: number;y: number;width: number;height: number;}; };export type LineShapeDrawStep {lines: Array[number, number];fillColor?: string;strokeStyle?: string;gradients?: Arraynumber; }; export type CircleShapeDrawStep {x: number;y: number;radius: number;startAngle: number;endAngle: number;anticlockwise: boolean;fillColor?: string; };export type roundRectShapeDrawStep {ctx: CanvasRenderingContext2D;x: number;y: number;width: number;height: number;radius: number;fillColor: any; };export type DrawStep | ({ type: DrawType.Text } (TextDrawStep | GetPropsTextDrawStep))| ({ type: DrawType.Image } (ImageDrawStep | GetPropsImageDrawStep))| ({ type: DrawType.LineShape } (| LineShapeDrawStep| GetPropsLineShapeDrawStep));export type DrawSteps ArrayDrawStep { drawData?: AnyObject; immediateDraw?: boolean } ; export const px2rpx (px: number) px / (uni.upx2px(100) / 100); export const rpx2px (rpx: number) uni.upx2px(rpx); 使用 import { getCurrentInstance, ref } from vue;const poster refPoster | undefined | any(undefined);poster.value new Poster(myCanvas, self, { isPixel: false });const self getCurrentInstance(); // 设置画布大小 poster.value.setCanvasSize(750, wrapperHeight.value); // 绘制前先清空画布 poster.value.clearAll(); poster.value.drawSteps [{// 背景高斯模糊图片type: DrawType.Image,getProps: (steps: DrawSteps) {return {image: flurBg.path,x: 0,y: 0,width: 750,height: 308,};},}, ];await poster.value.draw((res: any) {uni.hideLoading();});
http://www.zqtcl.cn/news/636387/

相关文章:

  • 张掖北京网站建设新闻事件
  • 济南网站建设(力选聚搜网络)wordpress文章中写代码
  • 网站后台忘记密码买购网十大品牌网
  • 360免费建站网页链接石家庄建设局网站怎么打不开
  • 东莞网站建做俄罗斯外贸的网站
  • 基于vue.js旅游网站开发网络营销的主要形式有建设网站
  • 医院网站建设要素国外电商网站
  • 甘肃两学一做网站可以制作h5的网站
  • 微信公众号手机网站开发wordpress 集赞系统
  • 怎么做会员积分网站免费ppt模板下载有哪些
  • 六安网站开发如何用微信小程序做网站
  • 华为云自助建站好不好seo技巧分享
  • 做淘宝客的网站wordpress+附件丢失
  • 苏州市城乡建设局网站首页做动漫网站的素材
  • 济南网站建设系统介绍服务网站开发费属于研发支出吗
  • 网站建设方案进行工期安排Wix做的网站在国内打不开
  • 网站后台后缀名qq免费申请账号
  • seo网站优化代码静态网站可以做哪些
  • 网页素材及网站架构制作个人单页网站模板
  • 微小店网站建设价格建设网站设备预算
  • 电子商城网站开发公司泰州网络营销
  • 网站建设公司利润分配一些常用的网站
  • 鄂尔多斯做网站的公司北京企业网站设计报价
  • 南宁关键词网站排名wordpress付免签插件
  • 龙岩网站定制电子政务与网站建设方面
  • 东莞网站制作十强英语培训机构网站建设策划书
  • 住房和城乡建设部网站加装电梯苏州外发加工网
  • 企业网站管理系统带授权广州seo报价
  • 建设门户网站的意义旅游电商网站建设方案模板
  • 网站做动态图片不显示某购物网站开发项目