不断发展的 SEO 世界中,保持领先地位至关重要。如果你像我一样,你会发现随着搜索算法变得越来越复杂和竞争越来越激烈,SEO资源保持不变甚至减少。因此,我们必须不断寻求创新方法来简化工作流程并提高生产力,才能维持生计。
我们都知道自动化可以帮助我们完成更多工作,而无需增加人员或预算。我相信你们中的许多人都问过自己是否应该深入编码世界以学习如何自动化某些任务。或者,你们中的一些人甚至可能尝试要求一些开发资源来实现这一目标。
如果您仍在阅读,则意味着您在上面认出了自己。这篇文章是写给你的,我的病友!
虽然学习如何编码不一定是解决方案,但仍然有希望的灯塔:进入 ChatGPT。
凭借其处理各种任务的卓越能力,ChatGPT 可以助您一臂之力,在本文中,我们将探讨 ChatGPT 如何彻底改变您实现 SEO 自动化的方式,使您无需具备丰富的编码知识即可取得显着的成果。
但首先,让我们更深入地研究自动化的概念及其在 SEO 领域的意义。
自动化是使用技术和工具来简化和简化重复性或耗时任务的过程。它可以让您将宝贵的时间和精力分配给更具战略性的举措,而平凡和重复的活动则由其他系统无缝处理。
有效利用自动化的关键步骤之一是确定要自动化的正确任务。
虽然并非所有任务都适合自动化,但许多流程可以分解为可成功自动化的可管理组件。从长远来看,通过识别这些组件,您可以节省大量时间和精力。
清晰的问题定义对于任何自动化项目都是至关重要的。
它包括理解手头的任务、识别痛点以及定义期望的结果。明确定义的问题陈述为为 ChatGPT 编写有效的提示奠定了基础,并确保自动化流程与预期目标保持一致。
一旦任务被识别并分解,就可以为 ChatGPT 编写提示了。
提示充当提供给模型的指令或查询以生成所需的响应。编写有效的提示需要在足够具体以指导模型和允许模型灵活地生成创造性和准确的响应之间取得平衡。
1. 首先列出您每天或每周执行的任务。这些重复性任务的范围从数据分析和报告生成到关键字研究或内容优化以及您能想到的几乎所有其他任务。
2. 将您的列表分为您对如何自动化有大致了解的任务以及那些看起来具有挑战性或不熟悉的任务。前者可能涉及使用现有的工具、脚本或插件,而后者可能需要更多的研究或学习。
3. 优先考虑自动化时能带来最显着效益的任务。考虑诸如您将节省的时间、可能的准确性、可扩展性和潜在的投资回报率等因素。或者简单地考虑一下它是否可以让你保持理智。选择一项与您的目标相符且能够为您的日常工作带来切实改进的任务。
我曾经考虑过我可能想要自动化哪些重复性任务,并列出了一个非常简短的列表 - 事实上,从我记事起,我就一直在自动化尽可能多的工作。然而,有一些事情我宁愿不必做,即使它们每个月只发生几次。
从我的列表中,我找到了一个可以节省我一些时间并且还有可能提升我的报告质量的方法:向 Looker Studio 中的图表添加 Google 更新注释。
对于下面的示例,我刚刚使用了以下免费工具和服务:
作为下一步,我开始思考这可能如何运作。我过去确实有自动化经验,有时可以当场想出一个好的解决方案。
但如果您正在解决一个不容易找到解决方案的问题,请不要担心。在这里,您可以使用 ChatGPT 寻求潜在的解决方案,也可以进行搜索(通过您最喜欢的搜索引擎)以查找其他人针对同一问题提出的解决方案。由于 ChatGPT 有时可能有点太有创意,我更喜欢坚持经典的“只需 Google 即可”。我坚信我永远不是第一个遇到特定问题的人。
以下是我对自动化建议任务的想法:
ALT/标题:Google 更新页面和 Chrome 开发者工具呈现的 HTML 代码的屏幕截图,显示该页面是使用表格构建的。
为了验证我的思路,我将快速运行表格中的公式,看看数据是否按需要输入:
ALT/标题:Google 表格中的屏幕截图显示第一个表中的数据
虽然此公式有效,但它仅引入页面上的第一个表(或特定的一个表,但不是全部)。如果我想要的只是今年的更新,那么使用这个公式就足够了。不幸的是,我希望在报告中包含历史数据,因此我需要导入所有表格。
现在我可以将上面的笔记总结为 ChatGPT 的提示:
ALT/标题:ChatGPT 提示的屏幕截图,询问:您好,我想使用 ImportHTML 功能将网页上多个表中的信息获取到 Google 表格中。如果有多个表,我该怎么办?
ALT/标题:ChatGPT 响应的屏幕截图,其中包含有关如何从网页导入表的详细信息。
有趣的是——我们肯定会陷入“我需要帮助”的境地,因为我不熟悉 AppScript。我还注意到,除了代码之外,我还得到了说明和注释——这对我理解它的功能非常方便。
我转到 Google Sheets > 扩展 > AppScript 并在此处创建一个新项目。我将其命名为“Google Updates”,然后将此处的代码替换为 ChatGPT 提供的代码。
在 AppScript 中进行任何更改时以及运行代码之前,请务必点击“保存”。
否则,您可能会因替换但未保存的代码而出现错误,并且必须花时间调试不存在的问题。
看起来 ChatGPT 为我创建了一个特殊的函数,我可以在表格中调用它 - 我按照说明操作,并将该函数与我想要从中获取更新的 URL 结合使用:
=importMultipleTablesFromURL(" https://status.search.google.com/products/rGHU1u87FJnkP6W2GwMi/history ")
但我收到一个错误:
ALT/标题:显示错误的 Google 表格的屏幕截图
我什至没有阅读错误消息,我只是将其复制到 ChatGPT 中:
ALT/标题:描述 Google 表格错误的 ChatGPT 提示的屏幕截图
使用我什至不理解的这条消息,ChatGPT 能够翻译我需要授权才能在表格中覆盖。然后它为我更新代码以包含此内容。
运行新代码后,我确实收到了“审查权限”对话框:
ALT/标题:AppScript 中的“需要授权”对话框的屏幕截图
然后我就可以验证这个脚本并允许它覆盖我的表格。
我再次运行代码,令人惊讶的是,我又收到了另一个错误:
ALT/Caption:AppScript 执行日志错误的屏幕截图
冲洗并重复,我将这个错误反馈给ChatGPT。事实上,我这样做了几次,所有的错误都出现了,并且我不断获得新的代码供我尝试。我只是在这里分享错误和回复的顶行:
ALT/标题:描述错误和响应的 ChatGPT 提示的屏幕截图
ALT/标题:描述错误和响应的 ChatGPT 提示的第二个屏幕截图
ALT/标题:描述错误和响应的 ChatGPT 提示的另一个屏幕截图
我在这里所做的几乎就是调试。我没有自己检查代码并试图找出错误是什么以及如何修复它们,而是将它们反馈给 ChatGPT,它会自行调试。
虽然中间有一些来回,但整个过程不到 5 分钟。我终于得到这个代码:
ALT/标题:ChatGPT 代码片段的屏幕截图
复制粘贴。节省。跑步。我终于成功执行了。切换到我的工作表,这是我看到的:
ALT/标题:显示 3 个表格的 Google Sheets 数据的屏幕截图
到目前为止,一切都很好!所有表格都正在导入,是时候进行一些改进了:
现在我可以将所有这些信息一次性或一次部分反馈给 ChatGPT。我觉得我需要按类型对请求进行分组,所以我首先尝试这样做:
ALT/标题:ChatGPT 提示的屏幕截图,要求仅保留第一个表的标题,并且在更新时不要覆盖数据
从下面的结果可以看出,这个要求不够明确。 ChatGPT 将所有数据放入一列中:
ALT/标题:Google 表格的屏幕截图,在一列中显示所有表格数据
是时候让我的沟通更加清晰,并解释我所看到的以及我想要得到的信息了:
ALT/标题:ChatGPT 提示的屏幕截图更清楚地询问要保留哪些标头
ALT/标题:Google 表格的屏幕截图,显示三个表格,中间有两个空行
肯定越来越近了!我现在只需要删除那些空行。我将再次解释我所看到的以及我想要的结果。
ALT/标题:ChatGPT 提示要求删除空行的屏幕截图
一些改进:
ALT/标题:ChatGPT 提示的屏幕截图,要求再次删除空行,因为仍留下一行
并成功:
ALT/标题:Google 表格的屏幕截图,显示所有三个表格列为一个表格
现在进行下一个改进:
ALT/标题:ChatGPT 提示要求从 A 列中提取更新名称的屏幕截图
结果不是我所期望的,所以我决定举一些例子,涵盖我能看到的所有模式。最后,我们到达了那里:
ALT/标题:Google 表格的屏幕截图,显示表格和带有更新名称的新列
那不是已经很漂亮了吗?让我们看看是否还能获得更新的结束日期,因为该信息不是由 Google 直接提供的。
ALT/标题:ChatGPT 提示要求计算更新长度的屏幕截图
请注意回复中 ChatGPT 如何知道 B 列和 C 列中有哪些值?那只是因为我们之前提到过它们 – ChatGPT 实际上无法看到我们的 Google 表格。
ALT/标题:Google 表格的屏幕截图,显示持续时间为无效持续时间格式
查看具有无效持续时间格式的行,我们可以很快看到只要持续时间不包括小时,它们就会发生。我决定要求 ChatGPT 在计算结束日期之前将持续时间四舍五入到整天 - 这样我们就可以绕过该列中包含不同类型数据的问题。
ALT/标题:Google 表格的屏幕截图显示了预期的持续时间
既然数据看起来不错,那么只剩下一件事情要做了——把这整件事列入时间表。
这可以通过使用触发器从 AppScript 完成,但由于我们使用的是 ChatGPT,我们不妨向它询问最后一个请求:
ALT/标题:ChatGPT 提示要求添加每周触发器的屏幕截图
瞧,这是包含触发器的最终代码:
function importTableAndCalculateUpdateType() {
var url="https://status.search.google.com/products/rGHU1u87FJnkP6W2GwMi/history"; // Replace with the URL of the webpage containing the tables
var response=UrlFetchApp.fetch(url);
var content=response.getContentText();
var tables=content.match(/<table[\s\S]*?<\/table>/g);
var sheet=SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastRow=sheet.getLastRow();
// Clear the sheet except for the first row (header)
if (lastRow > 1) {
sheet.getRange("A2:E" + lastRow).clearContent();
}
var data=[];
tables.forEach(function(table, index) {
var tempData=[];
var tableRows=table.match(/<tr[\s\S]*?<\/tr>/g);
tableRows.forEach(function(rowHTML, rowIndex) {
var rowData=[];
var cells=rowHTML.match(/<t[dh][\s\S]*?<\/t[dh]>/g);
cells.forEach(function(cellHTML) {
var cellText=cellHTML.replace(/<[^>]+>/g, '').trim();
rowData.push(cellText);
});
if (rowData.length > 0 && !(index > 0 && rowIndex===0)) {
tempData.push(rowData);
}
});
if (tempData.length > 0) {
data.push(tempData);
}
});
var startColumn=1; // Starting column to paste data
var startRow=1; // Starting row to paste data
for (var i=0; i < data.length; i++) {
var numRows=data[i].length;
var numCols=data[i][0].length;
sheet.getRange(startRow, startColumn, numRows, numCols).setValues(data[i]);
startRow +=numRows;
}
var updateTypeColumn=4; // Column index for "Update Type" (column D)
var endDateColumn=5; // Column index for "End date" (column E)
// Check and set header for "Update Type" and "End date" if they don't exist
if (sheet.getRange(1, updateTypeColumn).getValue() !=='Update Type') {
sheet.getRange(1, updateTypeColumn).setValue('Update Type');
}
if (sheet.getRange(1, endDateColumn).getValue() !=='End date') {
sheet.getRange(1, endDateColumn).setValue('End date');
}
for (var j=2; j <=sheet.getLastRow(); j++) {
var startDate=sheet.getRange(j, 2).getValue(); // Start date from column B
var duration=sheet.getRange(j, 3).getValue(); // Duration from column C
var endDate=calculatePotentialEndDate(startDate, duration);
sheet.getRange(j, endDateColumn).setValue(endDate);
var text=sheet.getRange(j, 1).getValue();
var updateTypes=extractUpdateTypes(text);
if (updateTypes.length > 0) {
var formattedText=updateTypes.map(word=> formatText(word.replace(/^\d{4}\s/, ''))).join(' ');
sheet.getRange(j, updateTypeColumn).setValue(formattedText);
} else {
sheet.getRange(j, updateTypeColumn).setValue('Other');
}
}
}
function createWeeklyTrigger() {
var day=1; // Monday
var hour=1; // 1 a.m. GMT
var timezone="GMT"; // Set the timezone
ScriptApp.newTrigger("importTableAndCalculateUpdateType")
.timeBased()
.onWeekDay(day)
.atHour(hour)
.inTimezone(timezone)
.create();
}
function extractUpdateTypes(text) {
var matches=text.match(/\d{4}\s([\w\s]+?)\supdate/ig);
return matches ? matches.map(match=> match.replace(/\supdate$/i, '').trim()) : [];
}
function formatText(str) {
return str.toLowerCase().replace(/(?:^|\s)\S/g, function(match) {
return match.toUpperCase();
});
}
function calculatePotentialEndDate(startDate, duration) {
var daysMatch=duration.match(/^(\d+)\s+days?/i);
var hoursMatch=duration.match(/^(\d+)\s+hours?,?\s?[\s\S]*/i);
if (daysMatch) {
var days=parseInt(daysMatch[1]);
var endDate=new Date(startDate);
endDate.setDate(startDate.getDate() + days);
return endDate;
} else if (hoursMatch) {
return new Date(startDate.getTime() + 1 * 24 * 60 * 60 * 1000); // Adding 1 day
} else {
return 'Invalid Duration Format';
}
}
这是最好的方法吗?可能不会。好处是我在 30 分钟内就完成了,只需要一些会话技巧,而且我不必花几个月的时间学习脚本语言。但是,如果我将来确实想学习,ChatGPT 会为我提供可能需要的所有解释。
如果您来这里只是因为想要成品,请随时创建我的 Google 更新表的副本,您可以将其与 Looker Studio 中的分析数据混合。
以下示例展示了将此数据叠加在流量时间线上后的报告的外观:
ALT/标题:Looker Studio 仪表板的屏幕截图,显示使用 Google 更新注释的网站流量时间线
您还可以对开始日期和结束日期进行三向混合,然后您可以选择任何更新并在图表上查看开始日期和结束日期。您甚至可以给它们不同的颜色。
ALT/标题:Looker Studio 混合面板的屏幕截图,显示三向混合
ALT/标题:Looker Studio 仪表板的屏幕截图,显示流量时间线上的 Coe 更新注释
或者,如果您愿意,您可以创建 Looker Studio 仪表板的副本,将 Google Analytics 数据与 Google Sheets 中的 Google Update 注释结合起来,并查看其设置方式。
如果您有兴趣使用 ChatGPT 自动执行不同类型的 SEO 任务,请继续阅读:
我希望早点做的事情:
如何改进这个过程:
如果您决定尝试此过程,请考虑与其他 SEO 分享您的成就。您的成功故事可能会激励人们采用这种方法并增强他们自己的 SEO 工作流程。
此外,在与 ChatGPT 互动时,请记住使用大量的“请”和“谢谢”——你永远不知道人工智能最终统治世界时会记住什么!
天小五与大家分享一个常用的查找引用函数即INDEXC函数,该函数表示在给定的单元格区域中,返回特定行列交叉处单元格的值或引用,那具体怎么使用?通过3个示例一起来看看相应的用法吧。
1、制作小抽奖箱
如何利用Excel制作简单的小抽奖箱?这里与大家分享借用INDEX函数来实现。
在单元格中输入公式=INDEX(A2:A17,RANDBETWEEN(2,COUNTA(A2:A17)))
公式说明:
COUNTA函数表示统计非空单元格格式
RANDBETWEEN函数表示随机生成整数
2、隔行提取数据
在单元格中输入公式=INDEX($A:$A,COLUMN(A1)+(ROW(A1)-1)*2)&""
公式说明:
COLUMN()表示获取相应的列号
ROW()表示获取相应的行号
3、一对多查询
输入公式=IFERROR(INDEX($A:$F,SMALL(IF($C:$C=$I,ROW(:),4^8),ROW(A1)),COLUMN(A1)),""),按Ctrl+Shift+Enter组合键,之后向右向下填充即可。
公式说明:
INDEX表示获取行列交叉数值
语法结构=INDEX(区域,行号,列号)
SMALL函数表示获取第几个最小值
语法结构=SMALL(查找的区域,指定要找第几个最小值)
IF函数表示根据条件进行判断并返回不同的值。
语法结构=IF(条件,条件成立时返回的值,条件不成立时返回的值)
者:前端Q
转发链接:https://mp.weixin.qq.com/s/ewFfXptccFs5KvjUINLGbQ
小试牛刀,实现了六款简单常见HTML5 Canvas特效滤镜,并且封装成一个纯JavaScript可调用的API文件gloomyfishfilter.js。支持的特效滤镜分别为:
1.反色
2.灰色调
3.模糊
4.浮雕
5.雕刻
6.合理
2.灰色调:获取一个预期点RGB值r,g,b则新的RGB值
newr=(r * 0.272)+(g * 0.534)+(b * 0.131);
newg=(r * 0.349)+(g * 0.686)+(b * 0.168);
newb=(r * 0.393)+(g * 0.769)+(b * 0.189);
3.模糊:基于一个5 * 5的卷积核
4.浮雕与雕刻:
根据当前预期的前一个预期RGB值与它的后一个重新的RGB值之差再加上128
5.总体:模拟了物体在镜子中与之对应的效果。
var canvas=document.getElementById("target");
canvas.width=source.clientWidth;
canvas.height=source.clientHeight;
**if**(!canvas.getContext) {
console.log("Canvas not supported. Please install a HTML5compatible browser.");
**return**;
}
// get 2D context of canvas and draw image
tempContext=canvas.getContext("2d");
var source=document.getElementById("source");
tempContext.drawImage(source, 0, 0, canvas.width,canvas.height);
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
var binaryData=canvasData.data;
function bindButtonEvent(element, type, handler)
{
if(element.addEventListener){
element.addEventListener(type, handler,**false**);
}else{
element.attachEvent('on'+type, handler);// for IE6,7,8
}
}
<scriptsrc=*"gloomyfishfilter.js"*></script> //导入API文件
gfilter.colorInvertProcess(binaryData, len); //调用 API
<meta http-equiv="X-UA-Compatible"*content=*"chrome=IE8">
效果演示:
CSS部分:
#svgContainer {
width:800px;
height:600px;
background-color:#EEEEEE;
}
#sourceDiv { float: left; border: 2px solid blue}
#targetDiv { float: right;border: 2px solid red}
filter1.html中HTML源代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="chrome=IE8">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Canvas Filter Demo</title>
<link href="default.css" rel="stylesheet" />
<script src="gloomyfishfilter.js"></scrip>
</head>
<body>
<h1>HTML Canvas Image Process - By Gloomy Fish</h1>
<div id="svgContainer">
<div id="sourceDiv">
<img id="source" src="../test.png" />
</div>
<div id="targetDiv">
<canvas id="target"></canvas>
</div>
</div>
<div id="btn-group">
<button type="button" id="invert-button">反色</button>
<button type="button" id="adjust-button">灰色调</button>
<button type="button" id="blur-button">模糊</button>
<button type="button" id="relief-button">浮雕</button>
<button type="button" id="diaoke-button">雕刻</button>
<button type="button" id="mirror-button">镜像</button>
</div>
</body>
</html>
filter1.html中JavaScript源代码:
var tempContext=null; // global variable 2d context
window.onload=function() {
var source=document.getElementById("source");
var canvas=document.getElementById("target");
canvas.width=source.clientWidth;
canvas.height=source.clientHeight;
if (!canvas.getContext) {
console.log("Canvas not supported. Please install a HTML5 compatible browser.");
return;
}
// get 2D context of canvas and draw image
tempContext=canvas.getContext("2d");
tempContext.drawImage(source, 0, 0, canvas.width, canvas.height);
// initialization actions
var inButton=document.getElementById("invert-button");
var adButton=document.getElementById("adjust-button");
var blurButton=document.getElementById("blur-button");
var reButton=document.getElementById("relief-button");
var dkButton=document.getElementById("diaoke-button");
var mirrorButton=document.getElementById("mirror-button");
// bind mouse click event
bindButtonEvent(inButton, "click", invertColor);
bindButtonEvent(adButton, "click", adjustColor);
bindButtonEvent(blurButton, "click", blurImage);
bindButtonEvent(reButton, "click", fudiaoImage);
bindButtonEvent(dkButton, "click", kediaoImage);
bindButtonEvent(mirrorButton, "click", mirrorImage);
}
function bindButtonEvent(element, type, handler)
{
if(element.addEventListener) {
element.addEventListener(type, handler, false);
} else {
element.attachEvent('on'+type, handler); // for IE6,7,8
}
}
function invertColor() {
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
var binaryData=canvasData.data;
// Processing all the pixels
gfilter.colorInvertProcess(binaryData, len);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
function adjustColor() {
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
var binaryData=canvasData.data;
// Processing all the pixels
gfilter.colorAdjustProcess(binaryData, len);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
function blurImage()
{
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
// Processing all the pixels
gfilter.blurProcess(tempContext, canvasData);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
function fudiaoImage()
{
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
// Processing all the pixels
gfilter.reliefProcess(tempContext, canvasData);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
function kediaoImage()
{
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
// Processing all the pixels
gfilter.diaokeProcess(tempContext, canvasData);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
function mirrorImage()
{
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
// Processing all the pixels
gfilter.mirrorProcess(tempContext, canvasData);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
滤镜源代码(gloomyfishfilter.js):
var gfilter={
type: "canvas",
name: "filters",
author: "zhigang",
getInfo: function () {
return this.author + ' ' + this.type + ' ' + this.name;
},
/**
* invert color value of pixel, new pixel=RGB(255-r, 255-g, 255 - b)
*
* @param binaryData - canvas's imagedata.data
* @param l - length of data (width * height of image data)
*/
colorInvertProcess: function(binaryData, l) {
for (var i=0; i < l; i +=4) {
var r=binaryData[i];
var g=binaryData[i + 1];
var b=binaryData[i + 2];
binaryData[i]=255-r;
binaryData[i + 1]=255-g;
binaryData[i + 2]=255-b;
}
},
/**
* adjust color values and make it more darker and gray...
*
* @param binaryData
* @param l
*/
colorAdjustProcess: function(binaryData, l) {
for (var i=0; i < l; i +=4) {
var r=binaryData[i];
var g=binaryData[i + 1];
var b=binaryData[i + 2];
binaryData[i]=(r * 0.272) + (g * 0.534) + (b * 0.131);
binaryData[i + 1]=(r * 0.349) + (g * 0.686) + (b * 0.168);
binaryData[i + 2]=(r * 0.393) + (g * 0.769) + (b * 0.189);
}
},
/**
* deep clone image data of canvas
*
* @param context
* @param src
* @returns
*/
copyImageData: function(context, src)
{
var dst=context.createImageData(src.width, src.height);
dst.data.set(src.data);
return dst;
},
/**
* convolution - keneral size 5*5 - blur effect filter(模糊效果)
*
* @param context
* @param canvasData
*/
blurProcess: function(context, canvasData) {
console.log("Canvas Filter - blur process");
var tempCanvasData=this.copyImageData(context, canvasData);
var sumred=0.0, sumgreen=0.0, sumblue=0.0;
for ( var x=0; x < tempCanvasData.width; x++) {
for ( var y=0; y < tempCanvasData.height; y++) {
// Index of the pixel in the array
var idx=(x + y * tempCanvasData.width) * 4;
for(var subCol=-2; subCol<=2; subCol++) {
var colOff=subCol + x;
if(colOff <0 || colOff >=tempCanvasData.width) {
colOff=0;
}
for(var subRow=-2; subRow<=2; subRow++) {
var rowOff=subRow + y;
if(rowOff < 0 || rowOff >=tempCanvasData.height) {
rowOff=0;
}
var idx2=(colOff + rowOff * tempCanvasData.width) * 4;
var r=tempCanvasData.data[idx2 + 0];
var g=tempCanvasData.data[idx2 + 1];
var b=tempCanvasData.data[idx2 + 2];
sumred +=r;
sumgreen +=g;
sumblue +=b;
}
}
// calculate new RGB value
var nr=(sumred / 25.0);
var ng=(sumgreen / 25.0);
var nb=(sumblue / 25.0);
// clear previous for next pixel point
sumred=0.0;
sumgreen=0.0;
sumblue=0.0;
// assign new pixel value
canvasData.data[idx + 0]=nr; // Red channel
canvasData.data[idx + 1]=ng; // Green channel
canvasData.data[idx + 2]=nb; // Blue channel
canvasData.data[idx + 3]=255; // Alpha channel
}
}
},
/**
* after pixel value - before pixel value + 128
* 浮雕效果
*/
reliefProcess: function(context, canvasData) {
console.log("Canvas Filter - relief process");
var tempCanvasData=this.copyImageData(context, canvasData);
for ( var x=1; x < tempCanvasData.width-1; x++)
{
for ( var y=1; y < tempCanvasData.height-1; y++)
{
// Index of the pixel in the array
var idx=(x + y * tempCanvasData.width) * 4;
var bidx=((x-1) + y * tempCanvasData.width) * 4;
var aidx=((x+1) + y * tempCanvasData.width) * 4;
// calculate new RGB value
var nr=tempCanvasData.data[aidx + 0] - tempCanvasData.data[bidx + 0] + 128;
var ng=tempCanvasData.data[aidx + 1] - tempCanvasData.data[bidx + 1] + 128;
var nb=tempCanvasData.data[aidx + 2] - tempCanvasData.data[bidx + 2] + 128;
nr=(nr < 0) ? 0 : ((nr >255) ? 255 : nr);
ng=(ng < 0) ? 0 : ((ng >255) ? 255 : ng);
nb=(nb < 0) ? 0 : ((nb >255) ? 255 : nb);
// assign new pixel value
canvasData.data[idx + 0]=nr; // Red channel
canvasData.data[idx + 1]=ng; // Green channel
canvasData.data[idx + 2]=nb; // Blue channel
canvasData.data[idx + 3]=255; // Alpha channel
}
}
},
/**
* before pixel value - after pixel value + 128
* 雕刻效果
*
* @param canvasData
*/
diaokeProcess: function(context, canvasData) {
console.log("Canvas Filter - process");
var tempCanvasData=this.copyImageData(context, canvasData);
for ( var x=1; x < tempCanvasData.width-1; x++)
{
for ( var y=1; y < tempCanvasData.height-1; y++)
{
// Index of the pixel in the array
var idx=(x + y * tempCanvasData.width) * 4;
var bidx=((x-1) + y * tempCanvasData.width) * 4;
var aidx=((x+1) + y * tempCanvasData.width) * 4;
// calculate new RGB value
var nr=tempCanvasData.data[bidx + 0] - tempCanvasData.data[aidx + 0] + 128;
var ng=tempCanvasData.data[bidx + 1] - tempCanvasData.data[aidx + 1] + 128;
var nb=tempCanvasData.data[bidx + 2] - tempCanvasData.data[aidx + 2] + 128;
nr=(nr < 0) ? 0 : ((nr >255) ? 255 : nr);
ng=(ng < 0) ? 0 : ((ng >255) ? 255 : ng);
nb=(nb < 0) ? 0 : ((nb >255) ? 255 : nb);
// assign new pixel value
canvasData.data[idx + 0]=nr; // Red channel
canvasData.data[idx + 1]=ng; // Green channel
canvasData.data[idx + 2]=nb; // Blue channel
canvasData.data[idx + 3]=255; // Alpha channel
}
}
},
/**
* mirror reflect
*
* @param context
* @param canvasData
*/
mirrorProcess : function(context, canvasData) {
console.log("Canvas Filter - process");
var tempCanvasData=this.copyImageData(context, canvasData);
for ( var x=0; x < tempCanvasData.width; x++) // column
{
for ( var y=0; y < tempCanvasData.height; y++) // row
{
// Index of the pixel in the array
var idx=(x + y * tempCanvasData.width) * 4;
var midx=(((tempCanvasData.width -1) - x) + y * tempCanvasData.width) * 4;
// assign new pixel value
canvasData.data[midx + 0]=tempCanvasData.data[idx + 0]; // Red channel
canvasData.data[midx + 1]=tempCanvasData.data[idx + 1]; ; // Green channel
canvasData.data[midx + 2]=tempCanvasData.data[idx + 2]; ; // Blue channel
canvasData.data[midx + 3]=255; // Alpha channel
}
}
},
};
感谢阅读,如果你觉得我今天分享的内容,不错,请点一个赞,谢谢!!
*请认真填写需求信息,我们会在24小时内与您取得联系。