Advertisement
  1. Web Design
  2. UI Design

인라인으로 된 공유하기 메뉴는 어떻게 코딩할까?

Scroll to top
Read Time: 7 min

Korean (한국어) translation by Jin Ah Chon (you can also view the original English article)

이번 튜토리얼에서 우리는 소위 "인라인으로 된 공유하기 메뉴"의 제작 방법을 학습할 것입니다. 이 인터페이스는 독자가 페이지를 공유하고, 하이라이트 표시된 텍스트를 인용할 수 있는 메뉴를 띄우는 방식으로 동작합니다. 여러분은 Medium처럼 몇몇 유명한 사이트에서 이와 유사한 인터페이스를 발견할 것입니다.

공유하기 메뉴 제작을 시작하기 전에 Medium에서 유사한 인터페이스가 어떻게 동작하는지, 예를 들어 화면에 나타나 하이라이트 된 영역보다 어느 위치에 있는지, 좀 더 세밀하게 검토해 보겠습니다.  이는 우리가 기술적인 면에서 적절한 인사이트를 얻고, 스스로 코드를 작성하는 방법을 결정하게 해주는 유용한 과정입니다.

시작해보죠!

Medium 인터페이스 검토

아래 이미지에서 Medium에 있는 공유하기 메뉴가 하이라이트 된 텍스트의 중간에 있는 것을 볼 수 있습니다. 선택해서 하이라이트 된 길이가 한 단어이거나 한 문장 혹은 문단 전체인지 상관없이 말이죠.

Highlighted word with the sharing button in MediumcomHighlighted word with the sharing button in MediumcomHighlighted word with the sharing button in Mediumcom
Medium에 있는, 인라인으로 된 공유하기 UI

크롬 개발자 도구에서 작성된 스타일을 보면, 공유하기 메뉴 위칫값이 인라인 스타일에서 topleft 속성을 통해 주어졌음을 알게 됩니다. 또한, 변경자(modifier) class인 highlightMenu--active를 적용해 공유하기 버튼이 눈에 보이게 된다는 것을 알 수 있습니다. 

메모: 여러분이 변경자(Modifier)블록(Block), 요소(Element) 용어를 잘 모른다면, 이전 튜토리얼인 BEM 방법론 소개를 읽어보시기 바랍니다.

Medium에 있는 인라인 공유하기 메뉴의 위치와 관련한 스타일

Styles 탭에서 보면, CSS로 초기 위치를 absolute position으로 잡았고, z-index 속성은 페이지에서 다른 요소들보다 위에 올라가며, topvisibility 속성을 이용해 공유 버튼이 눈에 보이지 않게 설정하고 있음을 알 수 있습니다.

고로 우리가 해야 할 작업을 요약하자면,

  1. 선택된 부분의 중간 지점을 정할 수 있도록 선택된 영역의 길이를 가져오기
  2. 요소가 눈에 보이도록 변경자(modifier) 생성하기
  3. inline 스타일로 추가된 topleft 속성을 이용해 공유하기 메뉴의 위치 설정하기

공유하기 메뉴 제작

예제에서 페이스북과 트위터 버튼이 공유하기 메뉴에 들어갑니다. 페이스북과 트위터 아이콘을 SVG 형태로 전달하고, button과 소수의 div 요소를 이용해 아이콘을 감싸줍니다. 그리고 앞에서 본 코드에서 알 수 있듯이, 메뉴 아래에 삼각형 조각을 만드는 span를 추가합니다.

1
<div class="sharing">
2
    <div class="sharing__buttons">
3
        <button id="share" title="Share">
4
            <svg class="icon icon--facebook" version="1.1" xmlns="https://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512; width: 24px; height: 24px" xml:space="preserve"><g></g><g><g><path d="M426.8,64H85.2C73.5,64,64,73.5,64,85.2l0,341.6c0,11.7,9.5,21.2,21.2,21.2H256V296h-45.9v-56H256v-41.4 c0-49.6,34.4-76.6,78.7-76.6c21.2,0,44,1.6,49.3,2.3v51.8l-35.3,0c-24.1,0-28.7,11.4-28.7,28.2V240h57.4l-7.5,56H320v152h106.8 c11.7,0,21.2-9.5,21.2-21.2V85.2C448,73.5,438.5,64,426.8,64z"/></g></g></svg>
5
        </button>
6
        <button id="tweet" title="Tweet">
7
            <svg class='icon icon--twitter' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 512 512' style='enable-background:new 0 0 512 512; width: 24px; height: 24px' xml:space='preserve'><path d='M492,109.5c-17.4,7.7-36,12.9-55.6,15.3c20-12,35.4-31,42.6-53.6c-18.7,11.1-39.4,19.2-61.5,23.5

8
                C399.8,75.8,374.6,64,346.8,64c-53.5,0-96.8,43.4-96.8,96.9c0,7.6,0.8,15,2.5,22.1c-80.5-4-151.9-42.6-199.6-101.3

9
                c-8.3,14.3-13.1,31-13.1,48.7c0,33.6,17.2,63.3,43.2,80.7C67,210.7,52,206.3,39,199c0,0.4,0,0.8,0,1.2c0,47,33.4,86.1,77.7,95c-8.1,2.2-16.7,3.4-25.5,3.4c-6.2,0-12.3-0.6-18.2-1.8c12.3,38.5,48.1,66.5,90.5,67.3c-33.1,26-74.9,41.5-120.3,41.5

10
                c-7.8,0-15.5-0.5-23.1-1.4C62.8,432,113.7,448,168.3,448C346.6,448,444,300.3,444,172.2c0-4.2-0.1-8.4-0.3-12.5

11
                C462.6,146,479,129,492,109.5z'/>
12
            </svg>
13
        </button>
14
    </div>
15
    <span class="sharing__triangle"></span>
16
</div>

메뉴 색상과 모양에 관해 결정된 규칙은 없습니다. 여러분의 사이트 디자인과 일치하는 메뉴로 자유롭게 꾸미세요. 버튼 크기 즉, 높이와 너비는 관심을 둘 만합니다. 여기 공유하기 메뉴는 아래 이미지에서 보이는 것처럼 너비가 84px이고 높이가 40px 입니다. 나중에 공유하기 메뉴를 하이라이트 된 영역의 중간에 위치를 잡는 데 이 두 값을 사용할 것입니다.

Inline sharing menu size inspected through Chrome DevToolsInline sharing menu size inspected through Chrome DevToolsInline sharing menu size inspected through Chrome DevTools

초기 position과 visibility를 설정하는 스타일 코드입니다.

1
.sharing {
2
  position: absolute;
3
	visibility: hidden;
4
	top: 0;
5
	left: 0;
6
	z-index: 500;
7
}

그리고 마지막에 공유하기 버튼을 눈에 보이게 하려고 붙이는 class입니다.

1
.sharing--shown {
2
	visibility: visible;
3
}

공유하기 메뉴의 함수 제작

이 시점에 인라인 공유하기 메뉴는 페이지에서 눈에 보이지 않아야 합니다. 또한, 페이스북과 트위터 버튼을 클릭할 때도 공유하기 윈도우 창은 어디에서도 보이지 않습니다. 자, 이 섹션에서 우리가 생각한 대로 버튼이 동작하도록 자바스크립트를 작성하겠습니다. 아래의 getHighlight() 함수로 시작합니다.

1
function getHighlight() {
2
3
    var selection = window.getSelection(); // 1.

4
5
    var object = {
6
		parent : null,
7
		text   : '',
8
		rect   : null
9
    };
10
11
	// If selection is not empty.

12
    if ( selection.rangeCount > 0 ) {
13
        object = {
14
            text   : selection.toString().trim(), // get the text.

15
            parent : selection.anchorNode.parentNode, // get the element wrapping the text.

16
            rect   : selection.getRangeAt(0).getBoundingClientRect() // get the bounding box.

17
        };
18
    }
19
20
    return object; // 2.

21
}

이 함수는 다음과 같이 진행됩니다.

  • 네이티브 자바스크립 함수인 getSelection()을 이용해 하이라이트 된 영역을 가져옵니다.
  • 선택된 텍스트와 텍스트를 감싸는 요소와 선택된 영역의 Rectangle Object를 담고 있는 Object를 받아넘깁니다. Rectangle Object는 페이지 내 선택된 영역의 크기와 위치(top, bottom, left, right) 값을 줍니다.

다음 함수는 showMenu()라고 명명하겠습니다. 이름에서 짐작 가듯이, 이 함수는 공유하기 메뉴를 눈에 보이게 합니다.

1
var sharing = document.querySelector( '.sharing' );
2
3
function showMenu() {
4
5
	// 1.

6
    var highlight = getHighlight();
7
8
	// 2.

9
    if ( highlight.text === '' ) {
10
11
        sharing.setAttribute( 'class', 'sharing' );
12
        sharing.style.left = 0;
13
        sharing.style.top  = 0;
14
15
        return;
16
    }
17
18
	// 3.

19
	/**

20
	 * Only show the sharing button if the selected is a paragraph.

21
	 */
22
    if ( highlight.parent.nodeName !== 'P' ) {
23
        return;
24
    }
25
26
	// 4.

27
    var width = ( highlight.rect.width / 2 ) - 42;
28
    /**

29
     * The "42" is acquired from our sharing buttons width devided by 2.

30
     */
31
32
    sharing.setAttribute( 'class', 'sharing sharing--shown' );
33
	sharing.style.left = ( highlight.rect.left + width ) + 'px';
34
	sharing.style.top  = ( highlight.rect.top - 40 ) + 'px';
35
	/**

36
	 * "40" is the height of our sharing buttons.

37
	 * Herein, we lift it up above the higlighted area top position.

38
	 */
39
}

이 함수에 작성된 코드는 구체적으로 다음과 같이 진행됩니다.

  1. getHighlighted() 함수에서 Object를 받습니다.
  2. 하이라이트 된 영역에 텍스트가 들어 있지 않고 비어 있다면, 공유하기 메뉴를 숨기고 초기 위치로 설정합니다.
  3. 하이라이트 된 텍스트가 단락 안에 싸여있지 않다면 버튼을 눈에 보이지 않게 합니다.
  4. 마지막에 topleft position을 설정하고 공유하기 버튼이 눈에 보이도록 sharing--shown class를 붙입니다. 저는 몇몇 숫자의 출처가 어디인지 설명하는 주석도 코드에 추가로 작성하였습니다.

대다수의 사용자가 마우스를 사용해 웹에서 콘텐츠를 하이라이트 한다고 가정하겠습니다. 그래서 이 함수를 mouseup 이벤트에 바인딩(bind)합니다. 모바일 기기에서는 보통 자체적으로 텍스트를 선택하는 콘텍스트 메뉴(contextual menu)가 있으므로 이 튜토리얼에서는 웹에 중점을 두겠습니다.

safari iossafari iossafari ios
사파리 iOS에서 선택한 텍스트

콘텐츠가 적절하게 선택되도록 setTimeout() 함수를 이용해 100ms만큼 실행을 지연합니다.

1
document.body.addEventListener( 'mouseup', function() {
2
     setTimeout( showMenu, 100 );
3
} );

마지막 함수인 openShareWindow()는 메뉴에 있는 버튼을 클릭할 때 공유하기 창을 열어줍니다. 페이스북에는 자체의 자바스크립트 SDK가 있으므로 이번 튜토리얼에서는 기본적으로 이 함수를 트위터 공유하기 창으로 전달하는 데 사용할 것입니다.

1
function openShareWindow( url, w, h ) {
2
3
	var screenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
4
	var screenTop = window.screenTop !== undefined ? window.screenTop : screen.top;
5
	var width = window.innerWidth ? window.innerWidth : doc.documentElement.clientWidth ? doc.documentElement.clientWidth : screen.width;
6
	var height = window.innerHeight ? window.innerHeight : doc.documentElement.clientHeight ? doc.documentElement.clientHeight : screen.height;
7
8
	var left = ( ( width / 2 ) - ( w / 2 ) ) + screenLeft;
9
	var top = ( ( height / 2 ) - ( h / 2 ) ) + screenTop;
10
11
	var newWin = window.open( url, "", "scrollbars=no,width=" + w + ",height=" + h + ",top=" + top + ",left=" + left );
12
13
	if ( newWin ) {
14
		newWin.focus();
15
	}
16
}

클릭...클릭...

다음에는 공유 버튼을 click 이벤트와 바인딩하고 공유하기 창을 띄울 함수를 덧붙입니다.

1
// Facebook.

2
document.getElementById( 'share' ).addEventListener( 'click', function() {
3
4
    var highlight = getHighlight();
5
6
    if ( highlight.text !== '' && highlight.parent.nodeName === 'P' ) {
7
        FB.ui({
8
            method : 'share',
9
            mobile_iframe: true,
10
            href   : 'http://bitly.com/2aiHmCs',
11
            quote  : highlight.text // pass the text as Quote

12
        });
13
    }
14
15
    event.preventDefault();
16
} );

페이스북 공유 버튼에는 페이스북의 자바스크립트 SDK를 사용합니다. SDK에서는 quote 매개 변수를 통해 공유하기 창에 보일 텍스트를 전달할 수 있습니다.

트위터에서는 그와 같은 방식으로 된 자바스크립트 SDK를 제공하지 않습니다. 그래서 우리는 openShareWindow() 함수를 이용해 창 크기와 함께 트위터 가이드라인을 따르고 정형화된 URL을 전달합니다.

1
document.getElementById( 'tweet' ).addEventListener( 'click', function() {
2
3
    var highlight = getHighlight();
4
5
    if ( highlight.text !== '' && highlight.parent.nodeName === 'P' ) {
6
7
        var docURL = encodeURIComponent( 'http://bitly.com/2aiHmCs' );
8
        var tweetText = encodeURIComponent( highlight.text );
9
        var tweetURL = 'https://twitter.com/intent/tweet?via=wdtuts&url=' + docURL + '&text=' + tweetText;
10
11
        openShareWindow( tweetURL, 600, 420 );
12
    }
13
14
    event.preventDefault();
15
} );

트위터 공유하기 버튼을 클릭하면 창이 열리며 다음과 같은 화면이 보입니다.

마무리

인라인으로 된 공유하기 메뉴 제작 과정을 모두 마쳤습니다! 함수로 꽉 차있는 소스 코드나 제대로 동작하는지 확인하러 데모로 가 보세요. 다음에는 더 매력적인 경험을 전달하도록 transition이나 animation을 이용해 인라인 공유하기 메뉴를 향상시킬 수 있습니다.

그 외의 참고자료

공유하기 메뉴를 띄우고 동작하는 데 사용했던 몇 가지 자바스크립트 API가 있습니다. 이 중에 일부는 Envato Tuts+ 튜토리얼에서 이전에 언급한 적이 있습니다. 나머지는 여러분에게 생소할 것 같습니다. 다음은 제가 이 튜토리얼을 보완하는 데 참고했던 자료입니다.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.