キャンペーンなど当選者の抽選をする時、エクセルで関数を作っていた方々に朗報です!それ kintone で楽にできるのでは?ということで、抽選カスタマイズの実装方法を紹介します。
応募者データを kintone に溜めて、抽選します。抽選結果は 2 パターンでお知らせするように工夫します!
レコードは全件取得するように実装しているので、応募者数が多くなっても大丈夫です。(一人 1 回応募が前提)
- SweetAlert でポップアップ
- 電光掲示板風に表示
デモ環境で実際に動作を確認できます。
https://dev-demo.cybozu.com/k/297/
ログイン情報は
cybozu developer network デモ環境 で確認してください。
- 抽選への応募者データを集める kintone アプリの作成
- SweetAlert でポップアップカスタマイズ
- 電光掲示板風カスタマイズ
kintoneのアプリ作成
固定リンクがコピーされました
応募者データを溜めるための抽選アプリを kintone で作成します。
-
以下のフィールドがある「抽選」アプリを作成してください。アプリの作成方法は
こちらのヘルプ
を参照してください。
フィールドタイプ |
フィールド名 |
フィールドコード |
文字列(1行) |
名前 |
name |
文字列(1行) |
コメント |
comment |
-
サンプルのデータを数件登録しておきましょう。
JavaScript/CSSカスタマイズ
固定リンクがコピーされました
それではここからカスタマイズをしていきます。これから実装する JavaScript と CSS ファイル以外にも、3 つのライブラリ(
Cybozu CDN)を使うので、まずはそれらを「アプリの設定画面 > JavaScript / CSS でカスタマイズ」に設置します。
- jQuery
- https://js.cybozu.com/jquery/3.2.1/jquery.min.js
- SweetAlert 2
- https://js.cybozu.com/sweetalert2/v7.3.5/sweetalert2.min.js
- https://js.cybozu.com/sweetalert2/v7.3.5/sweetalert2.min.css
- Font Awesome
- https://js.cybozu.com/font-awesome/v4.7.0/css/font-awesome.min.css
以下のように JavaScript ファイルと CSS ファイルを分けて設置してください。(random_lottery.js と random_lottery.css はのちほど設置します)
ここまで下準備ができたら、本題の抽選カスタマイズに移ります。今回は 2 ステップあるので、順に見ていきましょう!サンプルコードのポイント解説については、次の「サンプルコード解説」で記載しています。
Step1. SweetAlertでポップアップ
固定リンクがコピーされました
まず 1 つ目は、抽選結果を SweetAlert でポップアップ表示をします。
以下の JavaScript と CSS ファイルを「アプリの設定 > JavaScript/CSS カスタマイズ」にアップロードして保存してください。
random_lottery.js
一覧画面にある抽選ボタンをクリックした際、作成した抽選ロジックに基づいて抽選し、SweetAlert でポップアップ表示するための JavaScript ファイルです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
/*
* Random lottery sample program
* Copyright (c) 2018 Cybozu
*
* Licensed under the MIT License
*/
jQuery.noConflict();
(($) => {
'use strict';
// レコード一覧イベントを取得
kintone.events.on('app.record.index.show', (event) => {
// ボタン増殖防止
if (document.getElementById('lottery-button') !== null) {
return;
}
// 抽選ボタン作成
const menu = kintone.app.getHeaderMenuSpaceElement();
const $lotteryButton = $('<button class="lottery-button" id="lottery-button" title="抽選"><i class="fa fa-gift" aria-hidden="true"></i></button>');
// ボタンクリック時の操作
$lotteryButton.click(() => {
// レコード全件取得
const fetchRecords = (appId, opt_offset, opt_limit, opt_records) => {
const offset = opt_offset || 0;
const limit = opt_limit || 100;
let allRecords = opt_records || [];
const params = {
app: appId,
query: 'order by レコード番号 asc limit ' + limit + ' offset ' + offset
};
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', params).then((resp) => {
allRecords = allRecords.concat(resp.records);
if (resp.records.length === limit) {
return fetchRecords(appId, offset + limit, limit, allRecords);
}
return allRecords;
});
};
// 抽選実行
return fetchRecords(kintone.app.getId()).then((allRecords) => {
// 抽選ロジック作成
const num = allRecords.length;
const rand = Math.floor(Math.random() * num);
const name = allRecords[rand].name.value;
// SweetAlertで当選者表示
return swal({
title: name + 'さん当選です!😆',
text: 'おめでとうございます☆*:.。. o(≧▽≦)o .。.:*☆',
timer: 3000,
showConfirmButton: false
});
});
});
$(menu).append($lotteryButton);
});
})(jQuery);
|
random_lottery.css
抽選ボタン要素用の CSS ファイルです。ボタン自体は、Font Awesome を使って kintone の標準的なボタンと見た目を同一にしています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/*
* Random lottery sample program
* Copyright (c) 2018 Cybozu
*
* Licensed under the MIT License
*/
/** 抽選ボタン **/
.lottery-button {
/* color: #a8a8a8; */
color: #f5a1dc;
font-size: 32px;
display: inline-block;
padding: 0 16px;
height: 48px;
border: 1px solid #e3e7e8;
background-color: #f7f9fa;
text-align: center;
}
/** 抽選ボタンホバー時 **/
.lottery-button:hover {
/* color: #3498db; */
color: #f33bb6;
}
|
ピンクの抽選ボタンをクリックしてみてください。ポップアップ表示がされたでしょうか?
Step2. 電光掲示板風カスタマイズ
固定リンクがコピーされました
2 つ目は、SweetAlert 表示の後に、電光掲示板も加える工夫をします。今回は CSS のアニメーションを使って実装しています。
下のファイルを、Step1 で作成した JavaScript と CSS ファイルに上書きして保存してください。
random_lottery.js
SweetAlert 表示の後に、電光掲示板が入り込んでくるようにする JavaScript ファイルです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
/*
* Random lottery sample program
* Copyright (c) 2018 Cybozu
*
* Licensed under the MIT License
*/
jQuery.noConflict();
(($) => {
'use strict';
// レコード一覧イベントを取得
kintone.events.on('app.record.index.show', (event) => {
// ボタン増殖防止
if (document.getElementById('lottery-button') !== null) {
return;
}
// 抽選ボタン作成
const menu = kintone.app.getHeaderMenuSpaceElement();
const $lotteryButton = $('<button class="lottery-button" id="lottery-button" title="抽選"><i class="fa fa-gift" aria-hidden="true"></i></button>');
// ボタンクリック時の操作
$lotteryButton.click(() => {
// レコード全件取得
const fetchRecords = (appId, opt_offset, opt_limit, opt_records) => {
const offset = opt_offset || 0;
const limit = opt_limit || 100;
let allRecords = opt_records || [];
const params = {
app: appId,
query: 'order by レコード番号 asc limit ' + limit + ' offset ' + offset
};
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', params).then((resp) => {
allRecords = allRecords.concat(resp.records);
if (resp.records.length === limit) {
return fetchRecords(appId, offset + limit, limit, allRecords);
}
return allRecords;
});
};
// 抽選実行
return fetchRecords(kintone.app.getId()).then((allRecords) => {
// 抽選ロジック作成
const num = allRecords.length;
const rand = Math.floor(Math.random() * num);
const name = allRecords[rand].name.value;
// SweetAlertで当選者表示
return swal({
title: name + 'さん当選です!😆',
text: 'おめでとうございます☆*:.。. o(≧▽≦)o .。.:*☆',
timer: 3000,
showConfirmButton: false
}).then(() => {
// marqueeで当選者表示
const headerSpace = kintone.app.getHeaderSpaceElement();
const $boardDiv = $('<div id="board" class="board"></div>');
const $boardDivInner = $('<div id="board-inner" class="board-inner"></div>');
$boardDivInner.html(name + 'さん当選です!おめでとうございます☆*:.。. o(≧▽≦)o .。.:*☆');
headerSpace.innerHTML = null;
$boardDiv.append($boardDivInner);
$(headerSpace).append($boardDiv);
});
});
});
$(menu).append($lotteryButton);
});
})(jQuery);
|
random_lottery.css
電光掲示板の要素用の CSS ファイルです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
/*
* Random lottery sample program
* Copyright (c) 2018 Cybozu
*
* Licensed under the MIT License
*/
/** 抽選ボタン **/
.lottery-button {
/* color: #a8a8a8; */
color: #f5a1dc;
font-size: 32px;
display: inline-block;
padding: 0 16px;
height: 48px;
border: 1px solid #e3e7e8;
background-color: #f7f9fa;
text-align: center;
}
/** 抽選ボタンホバー時 **/
.lottery-button:hover {
/* color: #3498db; */
color: #f33bb6;
}
/** マーキーさせたい部分 */
.board {
width: 100%;
height: 55px;
text-align: center;
font-size: 40px;
font-weight: bold;
background-image: radial-gradient(#0C94F5 10%, transparent 20%), radial-gradient(#F5C20C 10%, transparent 20%);
background-color: #fcfcfc;
background-size: 20px 20px;
background-position: 0 0, 10px 10px;
overflow: hidden; /* スクロールバーが出ないように */
position: relative; /* マーキーの内容部分の位置の基準になるように */
}
/* マーキーの内容部分の高さ確保 */
.board::after {
content: "";
white-space: nowrap;
display: inline-block;
}
/* マーキーさせたい部分(内側) */
.board > .board-inner {
position: absolute;
top: 0;
white-space: nowrap;
animation-name: marquee;
animation-timing-function: linear;
animation-duration: 20s;
animation-iteration-count: infinite;
}
/* マウスオーバーでマーキーストップ */
.board > .board-inner:hover {
animation-play-state: paused;
cursor: default;
}
/** マーキーアニメーション */
@keyframes marquee {
0% { left: 100%; transform: translate(0); }
100% { left: 0; transform: translate(-100%); }
}
|
ピンクの抽選ボタンクリックでポップアップ表示の後に、電光掲示板が現れたら成功です!
カスタマイズのポイントを解説します。
Promiseを使ってレコードの全件取得
固定リンクがコピーされました
kintone REST API における GET メソッドの一括取得は、500 件までという制限があるので、レコード全件取得できるように処理を回す必要があります。
ここでは「
offset の制限値を考慮した kintone のレコード一括取得について」を参考に、Promise を用いて全件取得できるようにします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// レコード全件取得
const fetchRecords = (appId, opt_offset, opt_limit, opt_records) => {
const offset = opt_offset || 0;
const limit = opt_limit || 100;
let allRecords = opt_records || [];
const params = {
app: appId,
query: 'order by レコード番号 asc limit ' + limit + ' offset ' + offset
};
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', params).then((resp) => {
allRecords = allRecords.concat(resp.records);
if (resp.records.length === limit) {
return fetchRecords(appId, offset + limit, limit, allRecords);
}
return allRecords;
});
};
// 抽選実行 以下省略
// return fetchRecords(kintone.app.getId()).then((allRecords) => {
|
ランダムに抽選を行うロジックの作成
固定リンクがコピーされました
Math.random()関数
と
Math.floor()関数
を用いて、乱数を作成して抽選します。
1
2
3
4
|
// 抽選ロジック作成
const num = allRecords.length;
const rand = Math.floor(Math.random() * num);
const name = allRecords[rand].name.value;
|
Promiseを使えるようにSweetAlert 2を利用
固定リンクがコピーされました
SweetAlert 2 以前だと Promise をうまく扱えないので、今回は Promise 内でも使えるように最新の SweetAlert 2 を利用します。
1
2
3
4
5
6
7
8
9
|
// SweetAlert2 で当選者表示
return swal({
title: name + 'さん当選です!😆',
text: 'おめでとうございます☆*:.。. o(≧▽≦)o .。.:*☆',
timer: 3000,
showConfirmButton: false
}).then(() => {
// 省略
});
|
マーキー表示用に工夫
固定リンクがコピーされました
電光掲示板風な見た目を作る(マーキー表示)ために CSS でアニメーションをつけます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
/** マーキーさせたい部分 */
.board {
width: 100%;
height: 55px;
text-align: center;
font-size: 40px;
font-weight: bold;
background-image: radial-gradient(#0C94F5 10%, transparent 20%), radial-gradient(#F5C20C 10%, transparent 20%);
background-color: #fcfcfc;
background-size: 20px 20px;
background-position: 0 0, 10px 10px;
overflow: hidden; /* スクロールバーが出ないように */
position: relative; /* マーキーの内容部分の位置の基準になるように */
}
/* マーキーの内容部分の高さ確保 */
.board::after {
content: "";
white-space: nowrap;
display: inline-block;
}
/* マーキーさせたい部分(内側) */
.board > .board-inner {
position: absolute;
top: 0;
white-space: nowrap;
animation-name: marquee;
animation-timing-function: linear;
animation-duration: 20s;
animation-iteration-count: infinite;
}
/* マウスオーバーでマーキーストップ */
.board > .board-inner:hover {
animation-play-state: paused;
cursor: default;
}
/** マーキーアニメーション */
@keyframes marquee {
0% { left: 100%; transform: translate(0); }
100% { left: 0; transform: translate(-100%); }
}
|
イベントなどの抽選でご活用いただけるとうれしいです。ぜひ CSS をいじりながら、自分好みの抽選アプリを作ってみてください!
- 画面を更新すると電光掲示板の表示を停止できます。更新しない限りは、常に流れている状態になります。