Leader:马上中秋节了,你在网站的console面板中画一个嫦娥奔月,要有逼格

Hello 大家好,我是一碗周,不是你想的那个“一碗粥”,是一个不想被喝掉的前端👨🏻‍💻,如果我写的文章有幸可以得到你的青睐,万分有幸~

Leader:小周,还有十来天就中秋节了,你这几天在咱们网站的console面板中画一个嫦娥奔月,咱也来蹭一波中秋节的热度。

我:啊?console面板画嫦娥奔月?

正文开始~
表情包1.jpg

Leader:对,这个工作就交给你了。

我:好的,好的(内心:还能这么操作?行吧,去研究研究怎么实现吧,可不能耽误我摸鱼)。

console对象

那既然是在console面板画画,肯定离不开console对象,console对象中的console.log()方法是我们前端开发人猿每天都在用的一个方法,可以说是调试利器。

但是console对象中除了log()方法,还存在console.info()console.warn()console.error等方法,这些方法基本都类型,区别就是输出的内容类型不一样。

除了上面几个比较简单的之外,还有几个比较有意思的方法。

打印表格

console对象中存在一个table()方法,接受一个必要的参数,这个参数可以是一个数组或者对象,最终的结果是以表格的形式显示的。

如下代码展示了console.table()的用法:

var arr = [
    { name: '张三', age: 18, sex: '男' },
    { name: '李四', age: 19, sex: '男' },
    { name: '王五', age: 20, sex: '男' },
]
console.table(arr)

代码运行结果如下所示:

打印表格.png

分组

当我们需要打印特别多的信息时,可能页面的数据过多无法快速准确的定位我们想要的信息。console对象中提供了两组方法可以帮助我们来完成这个分组操作,具体如下:

  • console.group()console.groudEnd()

  • console.groupCollapsed()console.groudEnd()

这两者的区别就是前者分组是默认展开的,后者默认折叠。

console.group()console.groupCollapsed()接受一个参数,表示分组名称;console.groudEnd()表示当前分组结束。

如下展示展示了分组的用法:

// 默认展开
console.group('person')
console.log('name: 张三')
console.log('age: 18')
console.groupEnd()
// 默认折叠
console.groupCollapsed('person')
console.log('name: 张三')
console.log('age: 18')
console.groupEnd()

代码运行结果如下所示:

分组.png

计数操作

console对象中的count()方法可以用来完成计数的操作,该方法接受一个可选的参数,即输出的内容,默认为default;该方法还可以根据不同的参数来分别计数。

如下代码展示了console.count()的用法:

// 默认参数
console.count()
console.count()
console.count()
// 根据不同参数分别进行计数
console.count('一碗周')
console.count('happy coding')
console.count('一碗周')
console.count('happy coding')
console.count('一碗周')
console.count('happy coding')

代码运行结果如下所示:

计数.png

样式美化

我们还可以为console.log()输出的样式进行美化,对输入的样式美化主要是通过%c来完成的。

我们先来看一下掘金浏览器插件中的console面板:

掘金console面板.png

我们可以看到这个样式就与默认的有所不同,实际上实现这种效果的代码是下面这样的:

console.log('%cHi! 我是掘金插件的产品经理,\n作为一名曾经的开发者,很高兴能以这样的方式与你认识,\n如果你对插件有什么要吐槽的或者好的想法分享', 'line-height: 30px')
console.log('欢迎给我发送邮件交流: %czhangshaozhuang@bytedance.com', 'line-height: 30px; color: red')

我们现在就对这个语法进行解析,如下图所示:

console样式详解.png

在遇到%c后,会将后面的样式作为%c后文字的样式,遇到下一个%c会结束,下一个%c还可以在下一个参数的位置写CSS样式,依次类推。

如下代码展示了一句话中多个%c,具体代码如下:

console.log('%c红色%c蓝色%c绿色', 'color: red;', 'color: blue;', 'color: green;')

代码运行结果如下所示:

多个样式.png

console中允许的CSS属性有限,具体可以参考MDN

如果想要设置多个属性,直接使用字符串的方式写出来的效果不易读,可以使用数组的方式将每一项写出,在通过join()方法拼接,示例代码如下所示:

// 将 CSS 属性放置数组内,通过 join 拼接为一个字符串
const styles = [
    'color: red',
    'background: yellow',
    'font-size: 24px',
].join(';')
console.log('%cHello 一碗周', styles)

画嫦娥奔月

经过前面对console对象的补充和复习,现在画嫦娥奔月可以有两种选择方案,具体如下:

  • 直接使用图片的方式

  • 实现字符画的方式

现在我们对着两种方式分别进行实现。

在console面板引入图片

我们前面学习了可以通过%c的方式来设置CSS属性,这个方式是支持background属性的,我们可以将嫦娥奔月的图片作为背景图引入,实现代码如下所示:

console.log('%c', "background-image: url('/image/change_small.png'); background-size:100%;")

理想的效果是在console面板显示下面这张图片

change_small.png

可能是由于浏览器兼容问题导致这个图片无法显示

一个兼容的嫦娥奔月

由于直接使用图片绘制存在兼容问题,这里我们字符画的方式来绘制嫦娥奔月。

首先我们通过js的方式引入一个图片,代码如下:

let img = new Image()
img.src = './image/change_small.png'
img.onload = () => {
    // 图片加载完毕执行
}

第二步,我们需要定义<canvas>元素,它不需要显示,为后面通过canvas获取像素点打基础:

<canvas id="canvas" hidden></canvas>

第三步,定义一个将图片渲染值<canvas>元素,并返回所有的像素点

function getPixelData() {
    const canvas = document.getElementById('canvas')
    canvas.width = img.width
    canvas.height = img.height
    const ctx = canvas.getContext('2d')
    // 将img绘制到 canvas 容器中
    ctx.drawImage(img, 0, 0, img.width, img.height)
    // 获取像素数据,该数据为一个二维数组,第一次表示高有多少个像素点,第二次表示宽中的像素点
    return ctx.getImageData(0, 0, img.width, img.height).data

}

第四步,根据像素点的颜色来决定拼接什么字符串,函数如下:

// 把像素数据拼接成字符
function joinStringDraw(pixel) {
    // 定义一个空的字符串,用来存储我们的字符画
    let str = ''
    // 定义一个步长,因为一个像素点在转换为字符画时,相当于转换为一个字符,一个字符的默认大小为14像素,也就是说如果步长为1的话,这张图片被放大了14倍
    let step = 4
    // 通过双重for循环来获取每一个像素点
    for (let h = 0; h < img.height; h += step) {
        str += '\n'
        for (let w = 0; w < img.width; w += step) {
            // 这里提前填充一个空格的原因是因为一个字符的高度一般是宽度的2倍,所以这里的目的是增加字符的宽度
            str += ' '
            // 获取一个像素点的rgb值
            let pos = (h * img.width + w) * 4,
                r = pixel[pos],
                g = pixel[pos + 1],
                b = pixel[pos + 2]
            // 透明像素点在这里会被识别为纯黑色,也就是 rbg(0, 0, 0),只要不是黑色就填充一个●,黑色区域就填充空格
            str += [r, g, b].join('') !== '000' ? '●' : ' '
        }
    }
    return str
}

第五步,编写图片加载完毕后执行的函数:

img.onload = () => {
    // 获取像素数据
    const pixelData = getPixelData()
    // 拼接字符画
    const str = joinStringDraw(pixelData)
    // 打印最终的str
    console.log(str)
}

最终运行解决如下:

嫦娥奔月.png

现在就可以放心的摸鱼了,哈哈哈~~

写在最后

本篇文章中的故事纯属虚构,写这篇文章主要是为了可以巩固一下console对象,毕竟这个对象是前端开发中一个很重要的对象。

大家伙既然看完了,欢迎点赞留言,谢谢各位看官。

编写不易转载请获得允许

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这里给出一个基于固定翼无人机模型的预测控制例子,其中有一个Leader和三个Follower。 首先,我们需要建立一个固定翼无人机模型,可以使用动力学模型来描述它的运动。该模型可以表示为: $$ \begin{aligned} \dot{x} &= v_x \\ \dot{y} &= v_y \\ \dot{z} &= v_z \\ \dot{v}_x &= \frac{1}{m} (F \cos \theta \sin \phi - D \sin \theta + g \cos \theta \cos \phi) \\ \dot{v}_y &= \frac{1}{m} (F \cos \theta \cos \phi + D \cos \theta \sin \phi + g \cos \theta \sin \phi) \\ \dot{v}_z &= \frac{1}{m} (F \sin \theta - D \cos \theta - g \sin \theta) \\ \dot{\phi} &= p + \tan \theta (q \sin \phi + r \cos \phi) \\ \dot{\theta} &= q \cos \phi - r \sin \phi \\ \dot{\psi} &= \frac{1}{\cos \theta} (q \sin \phi + r \cos \phi) \\ \dot{p} &= \frac{1}{I_x} (l + I_y r q - I_z q r) \\ \dot{q} &= \frac{1}{I_y} (m + I_z p r - I_x p r) \\ \dot{r} &= \frac{1}{I_z} (n + I_x p q - I_y p q) \end{aligned} $$ 其中,$x, y, z$是无人机的位置坐标,$v_x, v_y, v_z$是无人机的速度,$\phi, \theta, \psi$是无人机的欧拉角,$p, q, r$是无人机的角速度,$m$是无人机的质量,$F$是无人机的推力,$D$是无人机的阻力,$g$是重力加速度,$l, m, n$是无人机的力矩,$I_x, I_y, I_z$是无人机的惯性矩。 接下来,我们需要进行预测控制。首先,我们将Leader无人机的位置和速度作为参考信号,然后我们使用MPC(Model Predictive Control)算法来计算Follower无人机的控制输入,使其跟随Leader无人机。MPC算法需要在每个时间步骤中求解一个优化问题来计算控制输入。 在本例中,我们将使用Python编写MPC算法。我们需要定义有限时间内的预测模型,包括状态方程和输出方程,以及控制输入的限制。然后,我们使用QP(Quadratic Programming)求解器来求解优化问题,得到控制输入。 最后,我们将控制输入应用于Follower无人机的动力学模型中,使其跟随Leader无人机。我们可以使用ROS(Robot Operating System)来实现无人机的控制和通信,以及Gazebo来模拟无人机的运动。 总体来说,基于固定翼无人机模型的预测控制例子需要涉及到动力学模型、MPC算法、QP求解器、ROS、Gazebo等多个方面的知识和技术。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一碗周.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值