라벨이 javascript인 게시물 표시

자신을 제외한 최대 약수 구하기

 코딩테스트에서 자신을 제외한 최대 약수가 필요한 부분이 있어 구글 검색 후 만들어본 javascript 함수입니다. function getLastDivisor(num) { var divisor = 1; if (num > 1) { for (var i = 2; i <= Math.sqrt(num); i++) { if (num % i === 0) { divisor = num / i; break; } } } return divisor; }  구글 검색에서 나온 약수를 구하는 방식은 다음과 같습니다.  어떠한 수의 제곱근을 가지고 1차로 약수를 구합니다. 1차로 구한 약수로 입력한 수를 나누어 나머지 약수를 구합니다.  위 방법에서 자신을 제외한 최대 약수가 필요했기에 1차 약수에서 1을 제외하여 입력한 수 자신을 제외하고, 그 다음으로 큰 약수를 구하면 바로 반복문을 나오도록 했습니다.

자바스크립트 초기화된 배열 만들기

 자바스크립트에서 특정한 값으로 초기화된 배열을 만드는 방법은 아래와 같습니다. const arr1 = new Array(10).fill(0); // [0,0,0,0,0,0,0,0,0,0] const arr = new Array(10).fill().map((value, index, array) => index + 1); // [1,2,3,4,5,6,7,8,9,10]  'new Array(10)'를 사용해 길이가 10인 비어있는 배열을 만들 수 있습니다.  '.fill()'을 사용하면 단일 값으로 배열 내부를 채울 수 있습니다. '.fill(0)'이나 '.fill(null)'처럼 원하는 값을 넣을 수 있습니다.  단일 값이 아니라 순차적으로 변하는 값으로 초기화를 하기 위해서는 이어서 '.map()'을 사용하면 됩니다. 인자값에 함수를 정의하면 함수의 반환 값으로 새로운 배열을 만들어 반환합니다.  주의할 점은 'new Array()'를 사용해 만들어진 빈 배열은 '.map()'이 돌아가지 않습니다. '.fill()'을 사용해 어떤 값이라도 먼저 초기화를 해야 '.map()'이 돌아갑니다.

Node.js로 윈도우 바로가기 실행

 Node.js의 child_process.spawn을 사용해 외부 프로그램을 실행할 때 실행파일의 바로가기를 사용하려고 합니다.  하지만, 바로가기 파일을 그냥 호출하면 오류가 발생합니다. 그때는 아래 코드와 같이 'shell: true'옵션을 설정해야 합니다. // Node.js v14.x const { spawn } = require('child_process'); spawn('C:/Users/my/Desktop/Program.lnk', args, { shell: true });  윈도우 바로가기의 파일 확장자인 '.lnk'를 꼭 붙여야 하며, 실행시 인자값이 없는 경우는 args에 null을 넣으면 됩니다.  관련된 질문 페이지 :  https://stackoverflow.com/questions/41497183/spawning-a-lnk-windows-shortcut-with-node-js-gives-unknown-error  child_process.spawn 공식 문서 :  https://nodejs.org/dist/latest-v14.x/docs/api/child_process.html#child_process_child_process_spawn_command_args_options

Vue.js 같은 종류의 이벤트 여러 개 등록하기

 Vue.js 를 사용하여 하나의 이벤트에 두 개 이상의 핸들러 등록이 필요한 경우 아래와 같이 쉼표로 구분하여 등록이 가능합니다. <button @click="onClickA(), onClickB()" type="button"> </button>  주의사항으로  핸들러를 등록할 때는 변수형이 아니라 실행문으로 처리해야 합니다.  이렇게 실행문 형태로 핸들러를 등록 할 때 내부에서 이벤트 인자값이 필요한 경우에는 아래와 같이 '$event'를 인자로 추가하면 됩니다. <button @click="onClickA($event), onClickB($event)" type="button"> </button>

Three.js 에서 대상을 멀리서 봤을 때 자글거리는 증상

이미지
Three.js를 사용하여 대상을 표현하는데 자글거리는 증상이 나옵니다. 카메라를 이동해서 가까이 가면 증상이 나오지 않지만 멀리 떨어지면 나오는 증상이었습니다. 대상을 구성하는 요소들이 겹치면서 자글거리는 것 같다고 생각이 들었지만 어떻게 처리해야 하는지 알 수 없었습니다. 그러다가 다음과 같은 글을 찾았습니다. https://github.com/jeromeetienne/AR.js/issues/401 댓글에 나와있는 답변에서 아래와 같은 내용을 봤습니다. var renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true }); 공식 문서에서 "WebGLRenderer" -> "logarithmicDepthBuffer" 항목을 찾아보니 다음과 같은 설명과 예시를 볼 수 있었습니다. https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderer ( ctrl + f -> logarithmicDepthBuffer 검색 ) https://threejs.org/examples/#webgl_camera_logarithmicdepthbuffer 이 옵션은 깊이에 관련된 옵션으로 보였고, 옵션을 적용하니 문제는 쉽게 해결되었습니다.

Three.js 에서 카메라가 가까이 다가가면 특정 부분만 사라지는 경우

Three.js를 사용한 3D 공간에 캐릭터를 표시했습니다. 카메라를 이리저리 움직이며 보던 중에 가까이 접근하면 머리카락이 사라지는 증상을 알게 되었습니다. 이 문제를 찾아보기 위해 구글에 검색을 하니 비슷한 질문을 찾게 되었습니다. https://discourse.threejs.org/t/mesh-disapear-when-camera-close/2914 https://stackoverflow.com/questions/50501392/mesh-disapear-when-camera-close 보여지고 있는 object3D 객체의 "frustumCulled"값에 false를 넣으면 됩니다. 카메라에 보이지 않아도 렌더링 대상에 넣어주는 옵션으로 보입니다. https://threejs.org/docs/index.html#api/en/core/Object3D.frustumCulled 저는 mesh에만 적용하여 사용 했는데 소스는 다음과 같습니다. object3D.traverse(function (obj) { if (obj.isMesh) { obj.frustumCulled = false; } }); Object3D.traverse() 를 사용해 내부를 돌면서 mesh만 골라 "fustumCulled"를 설정하는 겁니다. 이렇게 하니 문제가 해결되었습니다. 이 문제는 애니메이션이 있는 대상에서 자주 일어난다고 합니다.

iOS Safari에서 음소거 자동재생이 안되는 경우

모바일 브라우저는 소리를 포함한 영상을 자동재생할 수 없습니다. YouTube도 그렇고, video 태그도 그렇고, 음소거를 해야 자동재생이 가능합니다. 그럼에도 iOS에서는 무조건 막는 경우가 있는데 사용하는 폰이 절전모드인지 확인해 봐야 합니다. 절전모드로 되어있는 아이폰에서는 자동재생이 무조건 막히는 것을 확인 했습니다. (제가 가지고 있는 안드로이드 폰의 경우, 절전모드로 되어 있어도 자동재생이 가능 했습니다.)

프로젝트단위로 webpack 실행하기

지금까지 webpack을 전역 저장소에 설치하고 커멘드창에서 'webpack'을 입력하여 실행했습니다. 인터넷에서 찾은 설명에는 개발하는 프로젝트별로 webpack를 설치한 후 사용하라고 되어 있지만 커맨드창에 'webpack'명령어를 바로 입력하면 전역에서만 실행이 됩니다. (전역에 webpack이 설치되어 있지 않으면 오류가 납니다.) 프로젝트별로 webpack를 실행하기 위해서는 npm의 'scripts'설정을 사용해야 합니다. ... "scripts": { "start" : "webpack --config webpack.config.js", "gogogo" : "webpack --config webpack.config.js" } ... ('--config' 옵션은 뒤에 나오는 경로의 설정파일을 사용한다는 의미 입니다.) npm start npm run gogogo scripts에 start, restart, stop, test 명령으로 설정한 경우, 위처럼 'npm' 뒤에 바로 붙여 사용할 수 있습니다. 이외의 명령은 'npm run' 뒤에 붙여 사용합니다. 'npm run'만 입력한 경우 사용가능한 scripts 명령이 표시됩니다. 'npm start'를 실행하면 개발자가 설정한 명령이 실행됩니다. 이 명령으로 실행되는 webpack은 npm이 설정된 로컬 저장소를 먼저 찾아보게 됩니다. webpack뿐 아니라 npm으로 설치된 실행 모듈은 이런 식으로 로컬 실행이 가능합니다.

laravel, fine uploader 5 사용시 해더 설정

laravel에 CSRF 보호기능 이 있기 때문에 파일 업로드 요청과 같은 POST요청은 해더 값에 별도의 토큰이 있어야 합니다. 자바스크립트 파일 업로드 라이브러리  fine uploader 5 를 사용하려면 해더값에 토큰을 넣어야 합니다. 해더에는 `X-CSRF-TOKEN`이라는 이름으로 토큰이 들어가 있어야 합니다. fine uploader 5에 이 해더를 적용하기 위해서는 아래 코드와 같이 'request.customHeaders' 항목에 추가하면 됩니다. var uploader = new qq.FineUploader({ element: document.getElementById('uploader'), request: { endpoint: 'url', customHeaders: { 'X-CSRF-TOKEN': 'TOKEN' } } }); 토큰 사용할 때는 laravel의 view소스 meta 태그에 지정해 두고, 자바스크립트를 이용하여 읽어 옵니다. 아래 jQuery에서 사용하기 위한 설명이 있습니다. 여기서 CSRF 토큰을 가지고 오는 부분을 참고하면 됩니다. CSRF-TOKEN 설정

웹팩 빌드 후에 다른 작업 실행하기

Webpack으로 빌드한 최신 파일은 설정을 통해 내가 원하는 경로에 넣을 수 있습니다. 그렇게 사용하던 도중, 그 파일을 다시 복사해 다른 경로에도 배포해야 할 일이 생겼습니다. 검색 실력이 모자라서 그런건지 기본 설정으로 처리하는 방법은 찾지 못했습니다. 결국 Webpack의 플러그인과 추가 별도의 js 파일로 처리하게 되었습니다. 핵심은 빌드가 끝난 후, 자동으로 다음 작업을 하는 것입니다. 그래서 찾은 게  Webpack Shell Plugin  입니다. 이 플러그인을 사용하면 빌드 후에 간단한 커맨드 명령어를 실행할 수 있습니다. plugins: [ new WebpackShellPlugin({ onBuildEnd: ['node ' + path.resolve(__dirname, 'buildFileCopy.js')] }) ] Webpack의 plugins 설정에 빌드가 끝나면 별도로 만든 `buildFileCopy.js`파일을 nodejs로 실행하도록 했습니다. `buildFileCopy.js` 파일 안에는 저에게 필요한 간단한 파일 복사 기능을 만들어 두었습니다. const path = require('path'); const copy = require('copy'); const RESET = "\x1b[0m"; const FG_RED = "\x1b[31m"; const FG_GREEN = "\x1b[32m"; const src = path.resolve(__dirname, 'dist/*.js'); const dest = path.resolve(__dirname, 'docs/js'); copy(src, dest, (err) => { if (err) { console.log(FG_RED); console.log(...

웹 QR 스캐너

자바스크립트로 직접 만든 QR 스캐너. [ QR 스캐너 ] 사용하기 위해서는 브라우저에서 카메라 접근을 허용해야 합니다. 데이터 값 앞에 `http://` 혹은 `https://` 가 붙은 URL 주소인 경우, 해당 페이지로 바로 이동합니다. 해당 페이지는 깃허브에서 제공하는 pages 서비스를 이용하고 있습니다. 소스는  깃허브 페이지 에서 보실 수 있습니다. QR 코드를 분석하는 라이브러리는 jsQR 을 사용합니다.

자바스크립트로 언더바표기를 낙타표기로 전환하는 법

 `DATA_NAME`형태의 값을 `dataName`로 변환하는 자바스크립트 let name = 'DATA_NAME'; name = name.toLowerCase().replace(/_[a-z]/g, function (str) { return str[1].toUpperCase(); }); console.log(name);  전체 값을 `str.toLowerCase()`를 사용해 소문자로 변환합니다.  `/_[a-z]/g' 정규표현식을 사용해 앞에 언더바가 붙은 소문자 알파벳을 찾습니다. 당연히 매칭되는 값은 `_n`같이 `_`로 시작하는 두 글자 문자열이 됩니다.  자바스크립트의 `str.replace('a', 'b')`는 두 번째 인자에는 교체될 문자열이나 함수를 넣을 수 있습니다. 두 번째 인자에 함수를 넣으면 매칭되는 대상을 첫 번째 인자로 받습니다. 그리고 이 함수가 반환한 값으로 대상을 교체하게 됩니다. 그렇기 때문에 정규표현식으로 감지되는 문자열에서 두 번째 값만 대문자로 변환하여 반환하면 원하는 형태를 얻을 수 있습니다.

자바스크립트에서 깊은 복사를 간편하게 하기

 자바스크립트 변수에 있는 값을 새로운 변수에 넣었을 때 숫자나 문자열 같은 경우는 값이 복사가 됩니다. var a = 1; var b = a; b = 2; console.log(a); //b의 값이 바뀌어도 a 값은 바뀌지 않는다.  하지만 object와 같은 객체가 들어가 있는 변수는 내부의 값이 같은 대상을 가리키게 됩니다. var c = {x: 1}; var d = c; d.x = 2; console.log(c.x); //c와 d가 같은 대상을 가리키고 있기 때문에 변경된 값이 출력된다.  간편하게 깊은 복사를 하는 방법은 아래와 같습니다. var e = {x: 1}; var f = JSON.parse(JSON.stringify(e)); f.x = 2; console.log(e.x); // 문자열로 반환된 값을 다시 객체로 변환하였기 때문에 값이 복사되었다.  주의사항, 간편하게 사용할 수 있다고 복사에 무조건 사용하면 안 됩니다. 객체의 메소드와 같이 함수는 복사되지 않기 때문입니다. 복사 대상이 가지고 있는 값의 특성을 고민해야 합니다. 자신이 만든 클래스로 구현된 인스턴스를 복사하는 것이라면 별도의 함수나, clone 메소드를 구현하여 값을 복사하는 게 좀 더 좋다고 생각합니다. (반복문이나 재귀를 사용하여 값을 일일이 새로운 객체에 넣는 방법.)

아이폰에서 getUserMedia() 사용하기

`webRTC` API를 지원하는 브라우저에서는 `navigator.mediaDevices.getUserMedia()`를 사용할 수 있습니다. 안드로이드폰에 설치되는 크롬에서는 예전부터 지원하고 있었지만 아이폰에서는 iOS11 이상에 설치되어 있는 사파리에서 지원하기 시작 했습니다. 기본적인 사용방법은 인터넷에 잘 나와 있습니다. 하지만 아이폰에서 사용하려고 보니 몇 가지 특이사항이 있어 적어둡니다. 사용한 기기는 아이폰5s iOS 11.4 입니다. 기본 소스는 다음과 같습니다. <HTML> <video id="video" autoplay playsinline></video> <Javascript> const userMedia = navigator.mediaDevices.getUserMedia({ audio: false, video: { width: 640, height: 480, facingMode: 'environment' } }); userMedia.then(function (stream) { const videoEl = document.getElementById('video'); const videoTracks = stream.getVideoTracks()[0]; console.log('카메라 이름 : ' + videoTracks.label); videoEl.srcObject = stream; }).catch(function (error) { console.error(error.message); }); 웹 페이지 `<video>`태그에 카메라 영상을 보여주는 소스 입니다. 예전에 만들어진 가이드는 `navigator.getUserMedia()`를 사용하라고 되어 있었는데, 최근에는 ` nav...

자바스크립트로 숫자와 알파벳으로 구성된 랜덤문자 만들기

숫자와 알파벳으로 구성된 랜덤한 문자를 반환하는 함수 입니다. randomString(count) { let str = ''; for (let i = 0; i < count; i++) { str += Math.floor(Math.random() * 36).toString(36); } return str; } `Math.floor()` 버림으로 인해 0~35 까지의 값이 나오면 `.toString(36)`를 사용해 36진수로 변환합니다. (36진수는 0~9 10 문자, a~z 26 문자 총 36개의 문자로 표현 합니다.) 이러한 동작을 인자값 `count`만큼 반복해서 원하는 길이로 만들어 내는 간단한 형태 입니다.

자바스크립트를 사용하여 URL 구분하기

자바스크립트를 사용하여 URL을 구분하는 함수 입니다. function parseUrl(url) { const aEl = document.createElement('A'); aEl.href = url; const arr = aEl.search.replace(/^\?/, '').split('&'); const searchObj={}; let queries; for (let i in arr) { queries = arr[i].split('='); searchObj[queries[0]] = queries[1]; } return { protocol: aEl.protocol, host: aEl.host, hostname: aEl.hostname, port: aEl.port, pathname: ('/' + aEl.pathname).replace(/^\/\//, '\/'), search: aEl.search, searchObj: searchObj, hash: aEl.hash }; } HTML의 `<a>`를 활용하는 방법으로 `<a>`에 URL을 적용한 후, 필요한 값만 뽑아서 객체로 반환 합니다. 간단하게 사용하기 좋습니다. `http://url.com/index.html?a=1&b=2` 형태에 사용이 가능합니다. URL텍스트 값만 가지고 값을 구분하기 때문에 텍스트의 형태에 따라서 못 가지고 오는 값도 있습니다. 브라우저 마다 값의 형태가 다를 수 있습니다. 사용 전에 `console.log()`를 사용하여 값의 형태를 확인하고 추가적인 기능을 더 넣어야 할 수 있습니다. GET 방식으로 넘어오는 파라미터는 `qu...

Blogger에 개인 소스 추가하기

이미지
블로그에 별도로 기능을 추가하고 싶을 때가 있다. 외부에 있는 소스의 링크를 가지고 오고 싶을 수 도 있고, 자신이 간단하게 만들어 집어넣고 싶을 수 도 있다. 사용자가 코드를 추가할 수 있는 간단한 방법은 다음과 같다. 1. 관리자 페이지에서 레이아웃에 들어간다. 2. 레이아웃에서 필요한 부분에 가젯 추가를 누른다. 3. 기본 항목에 있는 HTML/JavaScript 를 추가한다. 3. 이름을 넣고, HTML 소스를 작성한다. 직접 작성한 소스가 복잡하다면 다른 에디터에서 작성하고 복사해 넣는 것을 추천한다. 저장 버튼을 누르면 Blogger에 적용된다.

텍스트 박스 입력시, 최신 값 가지고오기

텍스트 박스에 값을 입력할 때, 입력되는 순간마다 값을 가지고 와야하는 경우가 있다. `keydown` 이라던가 `input` 같은 이벤트를 사용한다. 이벤트 핸들러 내에서 바로 값을 가지고 오면, 지금 입력하고 있는 글자는 가지고 올 수 없다. 지금 입력되는 글자를 포함하여 가지고 오는 방법은 무엇이 있을까? 구글에서 "how to get incomplete text from input text"로 검색을 하니, 스택오버플로우에서 이에 대한 질문과 답변 을 찾았다. `mousedown`, `input` 이벤트는 변경사항이 적용되기 전에 값을 가지고 온다. 이는 필드에 도달하기 전에 이벤트를 차단할 수 있는 기능을 제공하기 때문이다. 값을 가지고 오기 전에 필드의 내용이 바뀔 수 있는 시간을 줌으로써 이 제한을 피할 수 있다. 간단한 방법으로는 `setTimeout()`를 사용하는 것이다. 이벤트 핸들러 내부에 `setTimeout(function () {} , 1)`을 사용하여 1ms의 간격만 두어도 필드의 내용이 최신 값으로 적용되어 현재 입력된 값을 같이 가지고 올 수 있다. el.addEventListener('input', function (evn) { // setTimeout 내에서는 this의 대상이 달라진다. var target = evn.target; setTimeout(function () { console.log(target.value); }, 1); });