캔버스에 부드러운 붓 같은 선을 그립니다.

Canvas에 부드러운 선을 그리고 싶습니다.



대학생 때 Flash로 만들었던 서예풍 그림 앱을 JS로 다시 써 보았습니다.
htps : // 후지후 r마 t. 코 m/아 스트로_펜/
※이번은 스마트폰판의 이야기가 됩니다.

서예풍이므로 붓으로 그린 ​​것처럼 선의 굵기가 변화하도록 만들고 있습니다. (체험하고 싶은 분은 [설정]에서 모드를 "붓"으로 해보십시오.) 일반적으로 이러한 스마트 폰으로 캔버스에 그림을하는 앱은 선 (lineTo)을 사용하여 궤적을 그린다고 생각합니다. 그렇다면 손가락을 빨리 움직이는 「발네」등의 때에 어색한 선이 생겨 버리기 때문에, 이번은 조금 무겁습니다만, 매끄러운 선을 그리는 프로그램을 써 보았습니다.

그려 본 글입니다. ※일부 겹쳐 썼습니다.

일반적인 코드와 그 약점



우선 lineTo로 그리는 프로그램의 구조입니다.
간단하게 구조를 설명하면 손가락을 움직이면 일정 시간마다 그 좌표가 취해지고, 그것을 직선을 사용하여 연결하는 것으로 궤적이 그려집니다. (예 : 여기의 기사와 같은 : htps : // 이 m/도 49/이고 ms/엣 f5156에 c9에 9999에 305b)

통상의 그림 앱이라면 이것으로 좋지만, 이번과 같이 굵기를 변화시킬 경우, 변화하는 굵기의 양을 궤적의 수로 나누어 각 궤적의 굵기를 바꾸어 가게 됩니다 . 방법으로서는 펜을 움직여 좌표를 취득했을 때에 화면을 누르고 있는 강도(e.touches[0].force)를 취득해, 그것을 궤적의 굵기로 변환합니다. 그러나, 현재의 스마트폰의 성능이라면 손가락을 빨리 움직였을 때에 좌표간의 거리가 커져 버려, 흐릿한 선이 되어 버립니다.

이미지

코드 개선



그래서 본 앱에서는 직선 대신에 원을 사용해, 일정 시간마다 손가락의 좌표를 취득. 현재의 좌표와 「현재의 좌표와 직전의 좌표의 사이」에 원을 보간해 그리는 프로그램으로 변경했습니다. 이것이라면 취득한 좌표간이 열려 있어도 보간하는 원의 수만큼 두께의 분할량이 많아져, 매끄러운 두께의 변화가 있는 선을 그릴 수 있습니다.

추기 : 일부 변수의 정보를 쓰는 것을 잊었으므로 수정했습니다.
    /*設定*/
    //補間する円の数(今回は50)
    divide_num=50;
    //円弧の始点と終点(0度から360度まで描く→円になる)
    pen_head_start_angle=0 * Math.PI / 180;
    pen_head_end_angle=360 * Math.PI / 180;
    //canvas要素とそのcontextを取得。今回はid=media
    const cvs = document.getElementById("media");
    const ctx = cvs.getContext("2d");

    /*ペンを動かしたとき(touchmoveとか)*/
    //画面を押している強さを取得。
    pen_force = e.touches[0].force;
    d_force=pen_force-old_force;

    //canvasの表示位置のズレを取得
    offsetx = $("#media").offset().left;
    offsety = $("#media").offset().top;

    //指のタッチ位置を取得
    new_x=e.changedTouches[0].pageX;
    new_y=e.changedTouches[0].pageY;
    //前回の指位置との差を計測
    dx=new_x-old_x;
    dy=new_y-old_y;

    //補間線を描く
    ctx.beginPath();
    for(i=0; i<divide_num; i++){
        ctx.arc(old_x+dx/divide_num*i-offsetx,
        old_y+dy/divide_num*i-offsety,
        (old_force+d_force/divide_num*i)*20,
        pen_head_start_angle,
        pen_head_end_angle, true);
    }
    ctx.fill();

    //古い座標、太さに現在の座標、太さを格納
    old_x=new_x;
    old_y=new_y;
    old_force=pen_force;

    /*ペンを動かしはじめたとき(touchstartとか)*/
    old_x=e.changedTouches[0].pageX;
    old_y=e.changedTouches[0].pageY;
    old_force=0;


손톱과 가볍게 누르는 강도를 바꾸면서 그리면 이런 느낌으로 그릴 수 있습니다.
(iPhone이라면 더 섬세하게 그릴 수있는 것 같습니다)

force를 취할 수 없는 기종의 대응



iPad 등 일부 기종에서는 force를 취득할 수 없었기 때문에 고정값으로 하는 모드도 작성했습니다.
(상기 프로그램에서 그 모드일 때 pen_force에 0.1을 설정하고 있습니다.)
게시하는 앱은 그곳이 기본값입니다.



이번은 목제가 두께가 매끄럽게 변화하는 선을 그릴 수 있는 프로그램이므로 만들지 않았습니다만, 응용하면 투명도나 무지개색으로 변화하는 선도 그릴 수 있습니다.

좋은 웹페이지 즐겨찾기