0

0

HTML5边玩边学(六)-汽车人,变形的详细介绍

黄舟

黄舟

发布时间:2017-03-29 15:07:21

|

2138人浏览过

|

来源于php中文网

原创

一、状态及其保存和恢复

在这一节开始之前,我们要先理解一下什么是状态以及状态的保存和恢复。玩过 MFC 编程的人经常能碰到这样的代码:

pOldPen=pDC->SelectObject(pNewPen)

我们在选择一个新画笔对象的同时,总是要保存住旧画笔对象,为什么要这样做呢?因为新画笔对象只是临时用一下,等用完了,我们想恢复到原来的画笔配置时,如果旧的配置事先没有被保存,这些配置就丢失了,也就没办法恢复了。

在 HTML5 绘图中,某一刻的状态就是当前这一刻上下文对象的一系列属性的配置值,只是,决定一个画笔状态的属性比较少,如颜色、粗细、线型之类的,而确定上下文状态的属性比较多,包括下面这些:

立即学习前端免费学习笔记(深入)”;

1、当前上下文对象的移动、旋转、缩放配置

2、当前上下文对象的 strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation 属性值

3、当前上下文对象的裁剪路径配置

上面这一系列配置决定了当前这一刻上下文对象的状态,其中移动、旋转、缩放、globalCompositeOperation(组合)、裁剪下面我们马上会讲到。

二、状态的保存与恢复

上面我们说某一刻的状态由那么多属性决定,我们要保存这一刻的状态就要把这些属性值一个一个都保存,恢复的时候在一个一个都设置回去,那也太麻烦了。确实是这样的,所以上下文对下提供了了两个简单的方法,对状态进行保存和恢复,他们是:

save( ) 和 restore( )

save 和 restore 方法可以多次调用,每调用一次 save 方法,调用时的状态(即一系列属性值)就压入一个栈中。

每调用一次 restore 方法,最后一次 save 的状态就被恢复,即出栈。

想象一下弹匣,第一颗被发射出去的子弹,总是最后一个被压入弹匣的。

 

三、变型

1、移动:translate(dx,dy)

这个方法看上去很简单,其实它包含了一定的数学含义,你可以认为是整个坐标系的原点发生了移动,新坐标系下任意一点(x,y)相当于原坐标系下的坐标为:

x'=x+dx
y'=y+dy

如果我们调用 ctx.translate(5,8) 改变上下文对象的坐标系状态,然后在新状态下的点(3,2)绘图,相当于图像被绘制到了原状态下的点(8,10)处,即

x'=5+3=8
y'=5+2=10

也许你会问,为什么要那么麻烦,直接在(8,10)处绘制比行吗?比如把

ctx.translate(5,8)
ctx.drawImage(img,3,2)

改成

ctx.drawImage(img,8,10)

这样不是更简单、更直接吗?

我的理解是,移动更多的情况下是为其他图形变换服务的,恰当的改变坐标原点可以让图形学计算更好理解,并带来很大方便,下面我举个简单的例子,假如:

有一条线段 ,是 x 轴正向上的一小段

y = 0 (1

如果以坐标原点为圆心,逆时针旋转90度,则线段与 y 轴正向重合,旋转后的线段为:

x = 0 (1

但是我们不可能每次旋转都以原点为圆心进行旋转,假如我们以线段的一个端点(1,0)为圆心进行旋转,我们怎么才能得到旋转后线段上每一点的坐标值呢?其实这个过程可以分为三步:

第一步:移动原点坐标到(1,0),新的线段依然在 x 轴上,但是方程变为了:y = 0 (0

第二步:以新坐标系的原点为圆心进行旋转,得到新坐标系下的线段 x = 0 (0

第三步:将新坐标系的原点移动到新坐标系下(-1,0)处,即将原点恢复到原来的位置,此时的线段为:x = 1 (0

第三步所得到的线段就是最后需要绘制的线段。

从这个例子我们可以看出来,即使在这么简单的情况下,如果不移动坐标原点来直接计算旋转后的图形,也是比较困难的。

提示当你移动坐标原点之前,千万别忘了保存状态,当然,绘制完毕后也别放了恢复状态。

2、缩放 scale(sx, sy)

这个同样很简单,sx, sy 是缩放比例因子,缩放后新坐标系下任意一点 (x,y) 相当于原坐标系下的坐标为:

x' = x * sx
y' = y * sy

同样,改变坐标系统总是不要忘记保存和恢复状态

3、旋转 rotate(A)

angle 是旋转角度,旋转后新坐标系下任意一点 (x,y) 相当于原坐标系下的坐标为:

FineVoice语音克隆
FineVoice语音克隆

免费在线语音克隆,1 分钟克隆你的声音,保留口音和所有细微差别。

下载

x' = x cosA - y sinA
y' = x sinA + y cosA

同样,改变坐标系统总是不要忘记保存和恢复状态

4、变形 transform(m11, m12, m21, m22, dx, dy)

其实前面讲的移动、缩放、旋转都是变形的特例,transform 方法的六个参数组成了一个变形矩阵,如下

m11 m21 dx
m12 m22 dy
0 0 1

调用 transform 方法就相当于用这些参数为上下文对象设置了新的变形矩阵,关于变形矩阵的具体内容可以参照图形学相关资料,下面给出几个简单特例:

移动 translate(dx,dy):相当于 transform(1,0,0,1,dx,dy)

缩放 scale(sx,xy):相当于 transform(sx,0,0,sy,0,0)

旋转 rotate(A):相当于 transform(cosA,sinA,-sinA,cosA,0,0)

以 (dx,dy) 为基准点旋转角度 A:transform(cosA, sinA, -sinA, cosA, dx(1-cosA) + dysinA, dy(1-cosA) - dxsinA)

以 (dx,dy) 为基准点进行 (sx,sy)比例缩放:transform(sx, 0, 0, sy, dx(1-sx), dy(1-sy))

还有很多其他更复杂的变形,大家可以参考图形学相关资料。

下面给出一个基准点变形的例子,鼠标在图像上的某点保持按下状态,图像就会以该点为基准点进行缩放或者旋转,松开按钮后图像复原。

提示:即缩放又旋转这个例子,并没有使用变形矩阵,而是用了四步简单变形复合而成。效果如下:


移动——在图像上按住鼠标并移动
基准点缩放——在图像某点处按住鼠标
基准点旋转——在图像某点处按住鼠标
基准点缩放同时旋转——在图像某点处按住鼠标

 

四、组合

所谓组合就是一个图形绘制在另一个图形之上,会出现什么效果。默认的情况下是上面的图形覆盖了下面的图形,称之为 source-over 。

上下文对象总共十二中组合类型,属性 globalCompositeOperation 被用来设置组合类型,如下:

globalCompositeOperation = type

type 是下面 12 种字符串值之一:

注意:上面所有例子中,蓝色方块是先绘制的,即“已有的 canvas 内容”,红色圆形是后面绘制,即“新图形”。 

五、裁剪路径

在第一篇文章中我们就介绍了上下文对象的两大类绘制方法,即绘制线条的 stroke 系列方法和填充区域的 fill 系列方法,其实,上下文对象还有一类绘制方法叫做裁剪 clip

什么是裁剪呢?打个不恰当的比方吧,你用一块布把电视机屏幕遮住了,这时候电视机屏幕上的任何变化你都看不见了。

但是,如果你布上裁剪出一块区域,那么至少这块区域里的屏幕变化你能看见。

当然裁剪区域之外的屏幕也在不停地变化(即也在重新绘制),只是你看不见罢了。这就是所谓的裁剪,平常在处理图像时经常会遇到这种需求。

那么什么又是裁剪路径呢?上面说要在布上裁剪出一块区域,这块区域是怎么来的呢?

这块区域是在裁剪动作 clip 之前,由绘图路径设定的,他可以是方形、圆形、五星形和其他任何可以绘制的轮廓形状。

所以,裁剪路径其实就是绘图路径,只不过这个路径不是拿来绘图的,而是设定显示区域和遮挡区域的一个分界线。

如果你不明白什么是绘图路径,在前的文章 HTML5边玩边学(2):基础绘图 中有介绍。

下面的例子用了两种方法进行裁剪。第一种方法显示一来回移动的圆形裁剪区域,大体流程如下:

1、清空画布

2、改变圆心位置

3、在新的圆心位置处设置一个圆形的裁剪区域

4、在画布上绘制美女图像

由于我们不停地在新位置处设定裁剪区域,我们就能看见裁剪区域在移动,而裁剪区域之外的图像并没有显示出来

我们用 clip 方法设置裁剪区域,之后绘制的图形只能显示裁剪区域内的一部分,而裁剪区域之外总是显示画布的背景色。

假如并不想完全遮挡裁剪区域之外的图像,比如我们想让裁剪区域之内的图像完全显示出来,但是裁剪区域之外的图像以半透明的方式显示出来,该怎么做呢?

这就要用到我们上面说的的组合知识了。第二中方法显示半透明的遮挡,大体思路如下:

1、清空画布

2、将画布的所有区域用一种半透明的颜色填充,这里我用的是灰色,透明度0.9

3、改变圆心位置

4、在新的圆心位置处以 XOR 方式绘制圆,这样和圆形重叠的部分将被擦除掉
这时候我们得到的图形效果是一个半透明的画布,上面有一块完全透明的圆形区域

5、 在第 4 步的基础上,以 destination-over 方式绘制美女图像,这时候美女图像将会出现在第 4 步图形效果的下方,想象一下,正好是我们想要的效果吧?!

代码



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><canvas id="canvas1" width="250" height="300" 

    onmousedown="trans.transform(event);"  

    onmouseup="trans.init(event);" 

    onmousemove="trans.translate(event);" 

    style="background-color:black">

    你的浏览器不支持 <canvas>标签,请使用 Chrome 浏览器 或者 FireFox 浏览器

</canvas><br/>

<input type="radio" name="r" id="r1" checked="checked">移动——在图像上按住鼠标并移动<br />

<input type="radio" name="r" id="r2">基准点缩放——在图像某点处按住鼠标<br />

<input type="radio" name="r"  id="r3">基准点旋转——在图像某点处按住鼠标<br />

<input type="radio" name="r"  id="r4">基准点缩放同时旋转——在图像某点处按住鼠标<br />



<canvas id="canvas3" width="250" height="300" style="background-color:black">

    你的浏览器不支持 <canvas>标签,请使用 Chrome 浏览器 或者 FireFox 浏览器

</canvas><br/>

<input type="button" onclick="move(1);" value="移动裁剪区域">

<input type="button" onclick="move(2);" value="移动蒙版">

<input type="button" onclick="stop();" value="停止移动"><br />



        <div>

            <table>

                <tr>

                    <td><canvas id="tut0" width="125" height="125"></canvas><br/><label id="lab0"></label></td>

                <td><canvas id="tut1" width="125" height="125"></canvas><br/><label id="lab1"></label></td>

                <td><canvas id="tut2" width="125" height="125"></canvas><br/><label id="lab2"></label></td>

                <td><canvas id="tut3" width="125" height="125"></canvas><br/><label id="lab3"></label></td>

                </tr>

                <tr>

                    <td><canvas id="tut4" width="125" height="125"></canvas><br/><label id="lab4"></label></td>

                <td><canvas id="tut5" width="125" height="125"></canvas><br/><label id="lab5"></label></td>

                <td><canvas id="tut6" width="125" height="125"></canvas><br/><label id="lab6"></label></td>

                <td><canvas id="tut7" width="125" height="125"></canvas><br/><label id="lab7"></label></td>

                </tr>

                <tr>

                    <td><canvas id="tut8" width="125" height="125"></canvas><br/><label id="lab8"></label></td>

                <td><canvas id="tut9" width="125" height="125"></canvas><br/><label id="lab9"></label></td>

                <td><canvas id="tut10" width="125" height="125"></canvas><br/><label id="lab10"></label></td>

                <td><canvas id="tut11" width="125" height="125"></canvas><br/><label id="lab11"></label></td>

                </tr>

            </table>

        </div>





<script type="text/javascript">

    //美女图的 Base64 编码

    IMG_SRC='data:image/gif;base64,/9j/4QDfRXhpZgAASUkqAAgAAAAFABIBAwA......';//省略四十字节



    //==========================================

    //基准点变形类

    //==========================================

    function Transform(){

        //获取画布对象

        this.ctx = document.getElementById("canvas1").getContext("2d");

        //创建图像对象

        this.img=new Image();

        //指定图像源

        this.img.src=IMG_SRC;

        this.interval = null;

        //鼠标按钮状态

        this.pressed=false;

        this.init();

    }

    

    //初始化图形

    Transform.prototype.init=function(){

        //鼠标按钮状态

        this.pressed=false;

        //停止计时器

        if(this.interval) clearInterval(this.interval);

        //变化值

        this.delta = 0.06;

        //清空

        this.ctx.clearRect(0,0,250,300);

        //重绘

        this.paint();

    }

    

    //绘制图像

    Transform.prototype.paint=function(){

        var that=this;

        var img=this.img

        if(img.complete)

            that.ctx.drawImage(img,0,0);

        else 

            var interval = setInterval(function(){

                if(img.complete){

                    that.ctx.drawImage(img,0,0);

                    clearInterval(interval);

                }

            },300);

    }

    

    //鼠标按钮按下后,开始变形

    Transform.prototype.transform = function(){

        //获取基准点

        this.dx=event.offsetX;

        this.dy=event.offsetY;

        //获取基准点

        this.startx=event.offsetX;

        this.starty=event.offsetY;

        //初始缩放比例

        this.sc=1;

        //初旋转角度

        this.angle=0;

        

        var that=this;

        if(document.getElementById("r1").checked)

            //鼠标按钮状态

            this.pressed=true;

        else if(document.getElementById("r2").checked)

            this.interval = setInterval(function(){that.scale()},50);

        else if((document.getElementById("r3").checked))

            this.interval = setInterval(function(){that.rotate()},50);

        else 

            this.interval = setInterval(function(){that.scaleAndRotate()},50);

    }

    

    //移动

    Transform.prototype.translate = function(){

        this.ddx=event.offsetX-this.startx;

        this.ddy=event.offsetY-this.starty;

        if(this.pressed){

            //清空

            this.ctx.clearRect(0,0,250,300);

            //保存状态

            this.ctx.save();

            //平移

            this.ctx.translate(this.ddx,this.ddy);

            //重绘

            this.paint();

            //绘制基准点

            this.ctx.fillStyle="red";

            this.ctx.fillRect(this.dx-5,this.dy-5,10,10);

            //恢复状态

            this.ctx.restore();

        }

    }



    //缩放变形

    Transform.prototype.scale = function(){

        //清空

        this.ctx.clearRect(0,0,250,300);

        //改变缩放比例

        this.sc=this.sc - this.delta;

        if(this.sc<0.2 || this.sc>2) 

            this.delta = -this.delta;

        //保存状态

        this.ctx.save();

        //以 (dx,dy) 为基准点进行 (sx,sy)比例缩放:transform(sx, 0, 0, sy, dx(1-sx), dy(1-sy))

        this.ctx.transform(this.sc, 0, 0, this.sc, this.dx*(1-this.sc), this.dy*(1-this.sc))

        //用新的变形矩阵重绘

        this.paint();

        //绘制基准点

        this.ctx.fillStyle="red";

        this.ctx.fillRect(this.dx-5,this.dy-5,10,10);

        //恢复状态

        this.ctx.restore();

    }

    

    //旋转变形

    Transform.prototype.rotate = function(){

        //清空

        this.ctx.clearRect(0,0,250,300);

        //改变缩放比例

        var PI = Math.PI;

        this.angle=this.angle + PI/60;

        //保存状态

        this.ctx.save();

        //以 (dx,dy) 为基准点旋转角度 A:transform(cosA, sinA, -sinA, cosA, dx(1-cosA) + dysinA, dy(1-cosA) - dxsinA)

        this.ctx.transform(Math.cos(this.angle), Math.sin(this.angle), 

                -Math.sin(this.angle), Math.cos(this.angle), 

                this.dx*(1-Math.cos(this.angle)) + this.dy*Math.sin(this.angle), 

                this.dy*(1-Math.cos(this.angle)) - this.dx*Math.sin(this.angle))

        //用新的变形矩阵重绘

        this.paint();

        //绘制基准点

        this.ctx.fillStyle="red";

        this.ctx.fillRect(this.dx-5,this.dy-5,10,10);

        //恢复状态

        this.ctx.restore();

    }

    

    //即缩放又旋转变形,没有使用变形矩阵

    Transform.prototype.scaleAndRotate = function(){

        //清空

        this.ctx.clearRect(0,0,250,300);

        //改变缩放比例

        this.sc=this.sc - this.delta;

        if(this.sc<0.2 || this.sc>2) 

            this.delta = -this.delta;

        var PI = Math.PI;

        this.angle=this.angle + PI/60;

        //保存状态

        this.ctx.save();

        //先移动原点到基点

        this.ctx.translate(this.dx,this.dy);

        this.ctx.scale(this.sc,this.sc);

        this.ctx.rotate(this.angle);

        this.ctx.translate(-this.dx,-this.dy);

        //用新的变形矩阵重绘

        this.paint();

        //绘制基准点

        this.ctx.fillStyle="red";

        this.ctx.fillRect(this.dx-5,this.dy-5,10,10);

        //恢复状态

        this.ctx.restore();

    }

    

    var trans = new Transform();

    

    //==========================================

    function Clip(){

        var canvas = document.getElementById("canvas3");

        this.ctx = canvas.getContext("2d");

        this.img=new Image();

        this.img.src=IMG_SRC;

        //移动方向

        this.delta=[3,3];

        //起始点

        this.pos_x = 225;

        this.pos_y = 120;

        //半径

        this.radius = 40;

        //画布的长和宽

        this.w = parseInt(canvas.getAttribute("width"));

        this.h = parseInt(canvas.getAttribute("height"));

    }

    

    Clip.prototype.draw1=function(){

        //碰撞检测

        if (this.pos_x < this.radius) {

            this.delta[0] = Math.random() % 4 + 5;

        } else if (this.pos_x > this.w - this.radius) {

            this.delta[0] = -(Math.random() % 4 + 5);

        }

        if (this.pos_y < this.radius) {

            this.delta[1] = Math.random() % 4 + 5;

        } else if (this.pos_y > this.h - this.radius) {

            this.delta[1] = -(Math.random() % 4 + 5);

        }

        this.pos_x += this.delta[0];

        this.pos_y += this.delta[1];



        this.ctx.clearRect(0, 0, this.w, this.h);

        //保存状态

        this.ctx.save()

        //移动变形

        this.ctx.translate(this.pos_x,this.pos_y);

        //设置裁剪区域

        this.ctx.beginPath();

        this.ctx.arc(0 ,0,this.radius,0,Math.PI*2,true);

        this.ctx.clip();         

        // 将图片画到画布上

        this.ctx.drawImage(this.img, -this.pos_x, -this.pos_y,this.w, this.h);

        //恢复状态

        this.ctx.restore();

    }

    

    Clip.prototype.draw2=function(){

        //碰撞检测

        if (this.pos_x < this.radius) {

            this.delta[0] = Math.random() % 4 + 5;

        } else if (this.pos_x > this.w - this.radius) {

            this.delta[0] = -(Math.random() % 4 + 5);

        }

        if (this.pos_y < this.radius) {

            this.delta[1] = Math.random() % 4 + 5;

        } else if (this.pos_y > this.h - this.radius) {

            this.delta[1] = -(Math.random() % 4 + 5);

        }

        this.pos_x += this.delta[0];

        this.pos_y += this.delta[1];



        this.ctx.clearRect(0, 0, this.w, this.h);

        //绘制灰色的半透明蒙版

        this.ctx.fillStyle="rgba(125,125,125,0.9)"

        this.ctx.fillRect(0, 0, this.w, this.h);

        //保存状态

        this.ctx.save()

        //移动坐标

        this.ctx.translate(this.pos_x,this.pos_y);

        //裁剪透明的圆形区域

        this.ctx.globalCompositeOperation = "xor";   

        this.ctx.fillStyle="white"

        this.ctx.beginPath();

        this.ctx.arc(0 ,0,this.radius,0,Math.PI*2,true);

        this.ctx.fill();       

        // 将图片画到蒙版的下面,即只露出透明区域

        this.ctx.globalCompositeOperation = "destination-over";   

        this.ctx.drawImage(this.img, -this.pos_x, -this.pos_y,this.w, this.h);

        //恢复状态

        this.ctx.restore();

    }



    var cl=new Clip();

    cl.interval=null;

    

    function move(id){      

        if(cl.interval)

            clearInterval(cl.interval)

        if(id==1){

            cl.ctx.clearRect(0, 0, 450, 300);    

            cl.interval=setInterval(function(){cl.draw1()},20);

        }

        else{

            cl.ctx.clearRect(0, 0, 450, 300);    

            cl.interval=setInterval(function(){cl.draw2()},20);

        }

    }



    function stop(){

        clearInterval(cl.interval)

    }

    

    var compositeTypes = [

        'source-over','source-in','source-out','source-atop',

        'destination-over','destination-in','destination-out','destination-atop',

        'lighter','darker','copy','xor'

    ];

    function drawComp(){

        for (i=0;i<compositeTypes.length;i++){

            var label = document.createTextNode(compositeTypes[i]);

            document.getElementById('lab'+i).appendChild(label);

            var ctx = document.getElementById('tut'+i).getContext('2d');



            // draw rectangle

            ctx.fillStyle = "#09f";

            ctx.fillRect(15,15,70,70);



            // set composite property

            ctx.globalCompositeOperation = compositeTypes[i];



            // draw circle

            ctx.fillStyle = "#f30";

            ctx.beginPath();

            ctx.arc(75,75,35,0,Math.PI*2,true);

            ctx.fill();

        }

    }

    drawComp();

</script>

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

77

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

49

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

21

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

10

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

14

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

26

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

9

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

303

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

23

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 7.1万人学习

HTML+CSS基础与实战
HTML+CSS基础与实战

共132课时 | 11.1万人学习

前端开发(基础+实战项目合集)
前端开发(基础+实战项目合集)

共60课时 | 4.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号