vj节点_创意编码—如何在JavaScript中创建VJ引擎

vj节点

by George Gally

通过乔治·加利

创意编码—如何在JavaScript中创建VJ引擎 (Creative Coding — How to create a VJ engine in JavaScript)

了解如何将JavaScript动态注入网页 (Learn how to dynamically inject JavaScript into webpages)

For years I’ve been using the browser for my performances and installations using my own simple homegrown VJ engine. And now, after you learn a few simple tricks, you can too…

多年来,我一直使用自己的简单本地VJ引擎将浏览器用于表演和安装。 现在,在您学习了一些简单的技巧之后,您也可以...

快速介绍 (A quick intro)

Firstly, what is a VJ engine? you might ask. And maybe even: what is a VJ? Wikipedia defines the characteristics of VJing as:

首先,什么是VJ引擎? 你可能会问。 甚至甚至:什么是VJ? 维基百科将VJing的特征定义为:

The creation or manipulation of imagery in realtime through technological mediation and for an audience, in synchronization to music.
通过技术中介实时创建或操纵图像,并与听众同步地为观众提供图像。

And a VJ engine is simply the software used for VJing.

VJ引擎只是用于VJing的软件。

But why would I build my own when there are so many VJ engines out there?

但是,当有如此多的VJ引擎出现时,为什么我要构建自己的引擎?

I never really loved VJ software — they always felt bloated and made everyone’s stuff look kinda the same. It’s kind of like when you first got your hands on Photoshop, and just blended a bunch of stuff together, added some filters, and it was cool (because it was the 90s). But most of all, I wanted tighter and better integration between developing content and the sound input frequencies.

我从未真正喜欢过VJ软件-他们总是感到felt肿,并使每个人的东西看起来都差不多。 这有点像您第一次接触Photoshop时,只是将一堆东西混合在一起,添加了一些滤镜,而且很酷(因为那是90年代)。 但最重要的是,我希望在开发内容和声音输入频率之间实现更紧密,更好的集成。

I rarely VJ these days, but it still drives most of my installations and performances — anywhere I need multiple visualisations I use RBVJ (the RB is for Radarboy — that’s me) as a wrapper/player.

这些天我很少使用VJ,但是它仍然可以驱动我的大多数装置和性能-在需要多幅可视化效果的任何地方,我都将RBVJ ( RB用于Radarboy ,就是我)用作包装器/播放器。

RBVJ has gone through a number of iterations over the years, as I’ve bounced from Flash, to Processing, and finally now to JavaScript, all using the same simple system.

多年来,RBVJ经历了多次迭代,正如我从Flash到处理,再到现在是JavaScript一样,都使用相同的简单系统。

I had previously open sourced it and my content (before the days of Git and not really knowing there was a thing called open-source). It won a bunch of awards, and I saw my content being used in a whole bunch of places which was nice. So I thought it was time to make it available for others again, along with a bunch of content to show how I go about creative coding.

我以前曾开源过它和我的内容(在Git出现之前,还不真正知道有一种叫做开源的东西)。 它赢得了很多奖项,我看到我的内容在很多地方都得到了很好的使用 。 因此,我认为是时候再次将其提供给其他人,以及一堆内容来展示我如何进行创意编码。

Ok, that’s a long enough introduction. Show me the money, you say!

好的,这是足够长的介绍。 你给我看看钱!

1.结构化内容 (1. Structuring the Content)

Essentially, a VJ engine is just a fancy content browser and player. So what we really need is a way to retrieve and play our content.

本质上,VJ引擎只是精美的内容浏览器和播放器。 因此,我们真正需要的是一种检索和播放内容的方法。

You could just dump all your content in a folder, but this system is what has worked best for me, allowing a simple structure for keyboard control:

您可以将所有内容转储到一个文件夹中,但是这个系统对我来说是最有效的,它提供了一种简单的键盘控制结构:

  • Shift 0–9 to change sets

    移0–9更改设置

  • Keys 0–9 to change banks

    0–9键更改银行

  • Keys a-z to choose content within the bank.

    按键az选择银行中的内容

This gives you 2,700 files to work with. If you really (really!?) wanted more, you could also double that by accessing another 26 files per bank with shift A-Z).

这样您就可以使用2,700个文件。 如果您真的(真的!?)想要更多,您还可以通过按AZ移位访问每个库中的另外26个文件来将其加倍。

Like most HTML projects, I have a simple top-level structure, and keep the VJ content in a numbered structure inside the art folder, like so:

像大多数HTML项目一样,我有一个简单的顶层结构,并将VJ内容保留在art文件夹内的编号结构中,如下所示:

index.html/css/js/art <- content goes here

My content folder (/art) contains 10 numbered folders, which I refer to as sets. Inside each set are another 10 numbered folders representing banks. And inside each bank are 27 individual numbered content files, like so:

我的内容文件夹(/ art)包含10个编号的文件夹,我称之为set 。 在每组里面还有另外10个编号编号的文件夹,代表银行 。 每个银行内有27个单独编号的内容文件,如下所示:

2.检索和播放内容 (2. Retrieving and Playing the Content)

Now we just need a way to access our files, which is done by injecting content into our index page.

现在,我们只需要一种访问文件的方式即可,方法是将内容注入到索引页面中。

And it’s pretty simple to do this.

做到这一点很简单。

The magic happens in a function called I’ve loadJS(). It creates a script tag within the page’s head and then injects some JavaScript into it (which would be our content). We trigger this function via a keypress (but could also be a midi or OSC signal) and pass the filename of the content we want into it. Then the script is available on the page.

神奇的事情发生在一个名为我的loadJS()函数中 它在页面的头部内创建一个脚本标签,然后向其中注入一些JavaScript(这将是我们的内容)。 我们通过按键触发该功能(但也可以是midi或OSC信号),然后将所需内容的文件名传递给它。 然后该脚本在页面上可用。

// INJECT JS ONTO PAGE
var my_script;
function loadJS(filename) {
// delete injected JavaScript if there’s been some loaded in before if (my_script != undefined)   document.getElementsByTagName("head")[0].removeChild(my_script);
// create a script element my_script = document.createElement(’script’); my_script.setAttribute("type", "text/javascript");
// Load the file in and insert it into the page’s head tag my_script.setAttribute("src", filename); document.getElementsByTagName("head")[0].appendChild(my_script);
}

We listen for keypresses with an event listener, which calls a function called onKeyDown(), like so:

我们使用事件侦听器侦听按键,该事件侦听器调用名为onKeyDown()的函数如下所示:

window.addEventListener( ’keydown’, function( event ) {   onKeyDown( event ); });

The listener passes the event object to the function, which contains a bunch of useful stuff. Here what we’re interested in: the event.keycode. Pressing the ‘a’ key gives us a keycode of 65, and pressing us a ‘z’ gives us a keycode of 90. So we simply subtract 65 from the keycode to give us the required file number and pass this value into a changeFile() function, which I’ll show in a bit.

侦听器将事件对象传递给函数,该函数包含一堆有用的东西。 这是我们感兴趣的: event.keycode 。 按“ a”键给我们键码为65,按“ z”给我们键码为90。所以我们只需从键码中减去65 给我们所需的文件编号 并将此值传递到changeFile()函数中,我将稍后显示。

Similarly we want keys 0–9 (keycodes 48 to 57, so subtract 48 ) to change banks. We also want test to see whether the shift key has been pressed to load sets. The event object has a handy event.shiftKey variable for this, so our onKeyDown function will look like so:

同样,我们希望键0–9(键代码48至57,所以减去48)来更改库。 我们还希望进行测试,以查看是否已按下Shift键来加载集合。 事件对象为此具有一个方便的event.shiftKey变量,因此我们的onKeyDown函数将如下所示:

// KeyPress Stuff
function onKeyDown( event ) {
var keyCode = event.keyCode;
// CHANGE FILE // keys a-z   if ( keyCode >= 65 && keyCode <= 90 ) {      changeFile(keyCode - 65);
// CHANGE SET AND BANK // keys 0-9   } else if ( keyCode >= 48 && keyCode <= 57 ) {
// Test whether the shift key is also being pressed      if( event.shiftKey ) {       changeBank( keyCode-48 );      } else {       changeSet( keyCode-48 );      }
}
}

The changeFile() function basically just takes the keypress and converts it into a URL. It calls our loadJS() function to inject the content into the page, and boom we’re away...

changeFile()函数基本上只需要按下按键并将其转换为URL。 它调用我们的loadJS()函数将内容注入页面,然后我们就离开了……

So our changeFile() function would look like this:

因此,我们的changeFile()函数将如下所示:

var current_file = 0;var current_set = 0;var current_bank = 0;
var art_location = "art/";
// FILE LOADER FUNCTIONS
function changeFile(file) {
current_file = file;  var loc = current_set + '/' + current_bank + '/' + current_file;  var filename = contentLocation + loc + '.js';  loadJS(filename);  document.location.hash = loc; //console.log("File: " + loc);
}

I also have an art_location variable in case I want to have different collections of visuals (so I can have different folders for different shows and installations). I also add the filename as a hash (https://127.0.0.1/#set/bank/file) to the browser’s URL to make it easy to see where I am.

如果我想拥有不同的视觉效果,我也有一个art_location变量(因此我可以为不同的演出和安装使用不同的文件夹)。 我还将文件名作为哈希(https://127.0.0.1/#set/bank/file)添加到浏览器的URL中,以方便查看我的位置。

Our changeBank() and changeSet() functions set the current_bank and current_set variables. Then they just call the changeFile() function to pull up the correct file.

我们的changeBank() changeSet()函数设置current_bankcurrent_set变量。 然后,他们只需调用changeFile()函数即可提取正确的文件。

For housekeeping, I also reset all the counters — setting current_file back to 0 when I change banks, and the current_bank back to 0 when I change sets. This is so I know that when I change banks, the file playing will be the first file in the bank. Similarly, when I change sets, the file playing will reset to be be the first file from the first bank of the current set (current_set/0/0.js).

为了看家,我也重置所有计数器-设置current_file回0当我改变银行和current_bank回到0当我改变集。 因此,我知道当我更换库时 ,正在播放的文件将是库中的第一个文件。 同样,当我更改集合时,正在播放的文件将重置为当前集合( current_set / 0 / 0.js )的第一个库中的第一个文件。

A bit of a mouthful, but the functions are actually super simple:

有点麻烦,但是功能实际上非常简单:

function changeSet(set) {
current_set = set;  console.log("changeSet: " + current_set);
// reset bank number  changeBank(0);
}
function changeBank(bank) {
current_bank = bank;  console.log("changeBank: " + current_bank);
// reset file number and load new file  changeFile(0);
}

And so the complete code for your basic VJ engine looks like this:

因此,基本VJ引擎的完整代码如下所示:

// FILE LOADER FUNCTIONS
var art_location = "/art";
var fileref;var current_file = 0;var current_set = 0;var current_bank = 0;
function changeFile( file ) {  reset()  current_file = file;  var loc = current_set + '/' + current_bank + '/' + current_file;  var filename = 'art/' + loc + '.js';  loadJS( filename );  document.location.hash = loc;  //console.log("File: " + loc);}
function changeSet( set ) {  current_set = set;  current_bank = 0;  console.log( "changeSet: " + current_bank );  // reset  changeFile( 0 );}
function changeBank( bank ) {  current_bank = bank;  console.log( "changeBank: " + current_bank );  changeFile( 0 );}
function reset(){  ctx.clearRect( 0, 0, w, h );  ctx2.clearRect( 0, 0, w, h );  ctx3.clearRect( 0, 0, w, h );  ctx.lineCap = "butt";}
// INJECT JS ONTO PAGE
function loadJS( filename ) {
if ( fileref != undefined ) document.getElementsByTagName( "head" )[ 0 ].removeChild( fileref );  fileref = document.createElement( 'script' );  fileref.setAttribute( "type", "text/javascript" );  fileref.setAttribute( "src", filename );  document.getElementsByTagName( "head" )[ 0 ].appendChild( fileref );
}

All that’s left to show you is how I structure the actual content files, which use an encapsulated function like so:

剩下要向您展示的是我如何构造实际的内容文件,它们使用如下封装的函数:

// RBVJ art
rbvj = function() {
draw = function() {     // do some creative coding here  }
}();

The function rbvj() is what gets injected into the page. It’s reused, so that every time a new file is inserted into my page, the memory gets flushed from all previous content.

函数rbvj()是注入页面的内容。 它已被重用,因此每次将新文件插入我的页面时,都会从所有先前的内容中清除内存。

By encapsulating the code (see the ‘()’ after the function), any code inside the rbvj() function will run automatically when the file is injected into the page.

通过封装代码(请参见函数后的“()”), rbvj()中的任何代码 文件插入页面后,该功能将自动运行。

You’ll notice that inside the content, I have a draw() function (this one from my own creative_coding.js utility script). It’s just a simple loop that uses JavaScript’s requestAnimationFrame() and is able to vary the frame rate.

您会注意到,在内容内部,我有一个draw()函数(该函数来自我自己的creative_coding.js实用程序脚本)。 这只是一个使用JavaScript的requestAnimationFrame()的简单循环 并能够更改帧速率。

var frame_number = 0;var frame_rate = 60;var last_update = Date.now();
function loop() {
var now = Date.now();  var elapsed_mils = now - last_update;
if ((typeof window.draw == 'function') && (elapsed_mils >= (1000 / window.frame_rate))) {    window.draw();    frame_number++;    last_update = now - elapsed_mils % (1000 / window.frame_rate);  }  requestAnimationFrame(loop);
};

And that’s pretty much it. You now have a working VJ engine in the bowser.

就是这样。 现在,bower中的VJ引擎正在运行。

3.其他一些可能会有所帮助的事情 (3. Some other things to know that may be helpful)

I normally just plug my computer’s sound input straight into an input from the venue’s mixer or amp (I use a version of my standard microphone input mic.js file, which you can read more about here). And I have keys setup (in my case, the plus and minus keys) to adjust the input levels up or down, so I don’t have to keep accessing the mixer.

通常,我通常只是将计算机的声音输入直接插入场地调音台或放大器的输入中(我使用标准麦克风输入mic.js文件的版本,您可以在此处了解更多信息)。 而且我有按键设置(在我的情况下,是加号减号 )可以向上或向下调整输入电平,因此我不必一直访问调音台。

Also note that for sound input, you’ll need a secure HTTPS connection — or if you use something like Atom’s Live Server, then that’s built in.

还要注意,对于声音输入,您将需要一个安全的HTTPS连接-或如果使用诸如Atom的Live Server之类的东西,那么它是内置的。

I also have a bunch of other keys set up for simple audio and visual filters (see how to make a pixelation filter here).

我还为简单的音频和视觉过滤器设置了许多其他键(请参阅此处如何制作像素化过滤器)。

I mostly don’t use a preview screen/interface, but it’s easy enough to build one. Just create a new HTML page and let the pages talk to each other through a socket.

我通常不使用预览屏幕/界面,但是构建一个界面很容易。 只需创建一个新HTML页面,然后让这些页面通过套接字彼此对话即可。

And finally, one last tip: when developing content, simply make a function to read in the current hash value of the browser, and call the loadFile() function on page load. That way, when you’re working on a file and you reload the page, that file is automatically displayed.

最后,最后一个技巧是:开发内容时,只需编写一个函数以读取浏览器的当前哈希值,然后在页面加载时调用loadFile()函数。 这样,当您处理文件并重新加载页面时,该文件将自动显示。

And that’s pretty much it. Hope this helps you get out there and show more of your content. As I mentioned previously, I’ve included a whole bunch of content for you to play around with and test so you can get a feel of how I create my stuff. If you use or alter any of it, I’d love to see how, where, and what you did with it. So please drop me a line.

就是这样。 希望这可以帮助您走到那里,并显示更多内容。 如前所述,我提供了很多内容供您试用和测试,以便您能体会到我如何创建自己的东西。 如果您使用或更改了其中任何一个,我很乐意了解您如何,在何处以及如何使用它。 所以请给我打个电话。

Happy coding. And thanks for reading!

快乐的编码。 并感谢您的阅读!

As usual the full code is available on Github.

和往常一样,完整的代码可以在Github上找到 。

This article is part of an ongoing series of tutorials on learning creative coding in pure JavaScript. As yes, I should be doing this in ES6, but wanted to keep this as simple as possible to understand.

本文是有关使用纯JavaScript学习创意编码的一系列教程的一部分。 是的,我应该在ES6中进行此操作,但希望保持其尽可能的简单易懂。

You can see previous all my previous creative coding tutorials here.

您可以在这里查看我之前所有的创意编码教程。

And follow me here for updates, techniques and eye candy:

并在这里关注我,以获取更新,技巧和眼神:

@radarboy3000 * Instagram photos and videos3,960 Followers, 843 Following, 1,082 Posts - See Instagram photos and videos from @radarboy3000www.instagram.comGeorge Gally (@radarboy_japan) | TwitterThe latest Tweets from George Gally (@radarboy_japan). Media artist, technologist, tinkerer, dreamer. Motion reaction…twitter.comRadarboyRadarboy. 130 likes · 7 talking about this. Art, design visualisation, hackswww.facebook.com

@ radarboy3000 * Instagram照片和视频 3,960关注者,843以下,1,082帖子-查看@ radarboy3000的Instagram照片和视频 www.instagram.com George Gally(@radarboy_japan)| Twitter 来自George Gally的最新推文(@radarboy_japan)。 媒体艺术家,技术专家,修补匠,梦想家。 运动React… twitter.com Radarboy Radarboy。 130喜欢·7谈论这个。 艺术,设计可视化,黑客攻击 www.facebook.com

翻译自: https://www.freecodecamp.org/news/how-to-create-a-vj-engine-in-javascript-b63b7fb1c87b/

vj节点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393897.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上传下载

# 默写 TCP UDP 文件夹中的代码# 完成一个上传和下载文件的小程序 # server端 :根据客户端需求自定义 # client端 # 客户端启动之后 # 选择 上传操作 还是 下载操作 # 如果是上传操作 : 输入要上传的文件路径 # 基础需求 :直接将文件上传到默认目录 # 进阶需求 :将…

qt 串口 环形缓存_qt linux串口 缓冲区多大

满意答案Zc的爱丶很美2016.09.11采纳率&#xff1a;51% 等级&#xff1a;9已帮助&#xff1a;515人一、程序设计的基础&#xff0c;例如&#xff1a;基本的编程语言基础&#xff0c;至少对数据类型、程序的结构及流程控制等最基本的内容要相当清楚&#xff01;另外有不少同学…

在.NET中使用SMTP发送邮件

这是一篇转载&#xff0c;可能对大家很有用啊&#xff0c;放首页看看是否有参考价值。本文提到的方案仍然不能算是完全解决所有问题&#xff0c;最佳的dotNET下通过SMTP&#xff08;带验证&#xff09;发送邮件的机制是什么&#xff0c;不知道大家有什么好的看法&#xff01; …

oracle堆,oracle被一堆insert和update堵死解决方案

当前位置:我的异常网 Oracle技术 oracle被一堆insert和update堵死解决方案oracle被一堆insert和update堵死解决方案www.myexceptions.net 网友分享于&#xff1a;2014-07-22 浏览&#xff1a;0次oracle被一堆insert和update堵死在生产环境下&#xff0c;几乎每天都会发生一次…

leetcode306. 累加数(回溯)

累加数是一个字符串&#xff0c;组成它的数字可以形成累加序列。 一个有效的累加序列必须至少包含 3 个数。除了最开始的两个数以外&#xff0c;字符串中的其他数都等于它之前两个数相加的和。 给定一个只包含数字 ‘0’-‘9’ 的字符串&#xff0c;编写一个算法来判断给定输…

使用Typescript和React的最佳实践

by Christopher Diggins克里斯托弗迪金斯(Christopher Diggins) 使用Typescript和React的最佳实践 (Best practices for using Typescript with React) There are numerous tools and tutorials to help developers start writing simple React applications with TypeScript.…

LeetCode || Copy List with Random Pointer

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null. Return a deep copy of the list. 思路1&#xff1a;最傻瓜的方法是首先遍历一次建立next关系的新list。然后第二次遍历处理random关系…

oracle存储过程多分支怎样写,如何从存储过程返回多行? (Oracle PL / SQL)

如何从存储过程返回多行&#xff1f; (Oracle PL / SQL)我想用一个参数创建一个存储过程&#xff0c;该存储过程将根据参数返回不同的记录集。 这是怎么做的&#xff1f; 我可以从普通SQL中调用它吗&#xff1f;5个解决方案65 votes这是如何构建一个函数&#xff0c;该函数返回…

京东布局消费物联网 聚合产业链共建生态

据Gartner发布的数据显示&#xff0c;到2020年&#xff0c;全球联网设备数量将达260亿台&#xff0c;物联网市场规模将达1.9万亿美元。如今&#xff0c;互联网已经从人与人的连接发展到人与物、物与物的连接&#xff0c;物联网时代带来。 5月9日&#xff0c;京东聚合三大运营商…

xshell监听端口_监听端口修改_笨办法学Linux 远程访问 (原理、实践、记录与排错)-视频课程_Linux视频-51CTO学院...

聪明人下笨功夫。本课程所倡导“笨办法”的核心是&#xff1a;● 深入理解原理● 精读man帮助、官方文档…● 做所有的实验&#xff0c;尽量不要复制粘贴&#xff01;● 详细记录实验过程● 使用思维导图等辅助工具● 享受排错的过程&#xff0c;在寻求帮助之前先尝试自己解决本…

leetcode632. 最小区间(堆+多指针)

你有 k 个升序排列的整数数组。找到一个最小区间&#xff0c;使得 k 个列表中的每个列表至少有一个数包含在其中。 我们定义如果 b-a < d-c 或者在 b-a d-c 时 a < c&#xff0c;则区间 [a,b] 比 [c,d] 小。 示例 1: 输入:[[4,10,15,24,26], [0,9,12,20], [5,18,22,3…

【SLAM】安装 g2o_viewer

2017年2月8日&#xff0c;那是一个阴天。为了完成高翔博士的《一起做RGB-D SLAM》教程&#xff0c;我在 Ubuntu 14.04 安装 g2o。遇到困难&#xff0c;怎奈我眼瞎&#xff0c;找错了方向&#xff0c;浪费时间&#xff0c;没有成功安装。 问题如下&#xff08;跳到最后一个问题描…

CSS动画快速介绍

Interested in learning CSS? Get my CSS Handbook 有兴趣学习CSS吗&#xff1f; 获取我的CSS手册 介绍 (Introduction) An animation is applied to an element using the animation property.使用animation属性将动画应用于元素。 .container { animation: spin 10s linear…

2_sat

要求字典序的情况的话&#xff0c;爆搜 不要求的话 1:建图&#xff0c;有向边A--->B的意义为选择A则必须选择B&#xff0c;一般一个点的两种取值情况会拆点。 2:缩点。 3:建反向图&#xff0c;跑拓扑排序&#xff08;有说不用建再跑&#xff0c;但我不懂为什么&#xff09;。…

[Spark][Python]Spark 访问 mysql , 生成 dataframe 的例子:

[Spark][Python]Spark 访问 mysql , 生成 dataframe 的例子&#xff1a; mydf001sqlContext.read.format("jdbc").option("url","jdbc:mysql://localhost/loudacre")\ .option("dbtable","accounts").option("user&quo…

ffmpeg mac 批量脚本_使用批处理脚本(BAT)调用FFMPEG批量编码视频

使用批处理脚本(BAT)编码视频非常方便&#xff0c;尤其当视频序列非常多的时候&#xff0c;更是省了不少简单重复性劳动。只要学会批处理里面几个基本的命令就行了&#xff0c;感觉和c/c差不多。set&#xff1a;设置变量(注意&#xff1a;变量一般情况下是字符串&#xff0c;而…

单实例oracle ha,Oracle单实例启动多个实例

Oracle单实例启动多个实例多实例运行&#xff0c;单个实例就是一个数据库&#xff01;一个数据库对应多个实例是RAC。Linux建立oracle的实例步骤&#xff1a;1、在linux服务器的图形界面下&#xff0c;打开一个终端&#xff0c;输入如下的命令&#xff1b; xhost ###远程调用…

leetcode357. 计算各个位数不同的数字个数(回溯)

给定一个非负整数 n&#xff0c;计算各位数字都不同的数字 x 的个数&#xff0c;其中 0 ≤ x < 10n 。示例:输入: 2 输出: 91 解释: 答案应为除去 11,22,33,44,55,66,77,88,99 外&#xff0c;在 [0,100) 区间内的所有数字。代码 class Solution {int numbers0;public int …

Shell编程 之 for 循环

1. 语法结构 2. 案例 2.1 批量解压缩 #!/bin/bashcd /root/test/ ls *.tar.gz > ls.log ls *.tgz >> ls.logfor i in $( cat ls.log )dotar -zxf $i &> /dev/nulldone rm -rf ls.log ~ …

react实战课程_在使用React一年后,我学到的最重要的课程

react实战课程by Tomas Eglinskas由Tomas Eglinskas 在使用React一年后&#xff0c;我学到的最重要的课程 (The most important lessons I’ve learned after a year of working with React) Starting out with a new technology can be quite troublesome. You usually find …