Articulate Riseに「Codeブロック」が登場
- Hiroshi Oto

- 2 日前
- 読了時間: 10分

生成AIと組み合わせて広がるeラーニングの可能性
Articulate Riseに新しく「Codeブロック」機能が追加されました。この機能により、HTML・CSS・JavaScriptなどのコードをRiseのレッスン内に直接埋め込むことができるようになりました。Riseはこれまで、シンプルで直感的に美しいeラーニングを作れることが特徴でしたが、Codeブロックの登場によって表現の自由度はさらに広がります。
本ブログでは、この新機能の概要と、実際に使えるシンプルなコードサンプルを紹介します。
Codeブロックとは
Codeブロックは、HTML・CSS・JavaScriptを使ったコンテンツをRiseのコース内に埋め込める機能です。
これにより、例えば次のようなことが可能になります。
ミニクイズ
カウントダウンタイマー
シミュレーション
インタラクティブな診断
カスタムUI
これまでRiseだけでは難しかったインタラクティブ要素も、簡単に追加できるようになります。
Codeブロックの簡単なサンプル
例えば、次のようなミニクイズを作ることができます。動画を再生してご覧ください。
以下のコードをそのままCodeブロックに貼り付けるだけで動作します。 (コード例が、少し長いですがご容赦ください)
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>今日の気分は? - Game UI Edition</title> <style> * { box-sizing: border-box; } :root { --bg1: #0f1021; --bg2: #1b1f4a; --text: #ffffff; --panel: rgba(255, 255, 255, 0.12); --panel-border: rgba(255, 255, 255, 0.2); --glow: 0 0 20px rgba(255, 255, 255, 0.25); } body { margin: 0; min-height: 100vh; overflow: hidden; font-family: "Segoe UI", "Hiragino Sans", "Yu Gothic", sans-serif; color: var(--text); background: radial-gradient(circle at 20% 20%, rgba(255, 0, 128, 0.25), transparent 30%), radial-gradient(circle at 80% 30%, rgba(0, 255, 255, 0.2), transparent 30%), radial-gradient(circle at 50% 80%, rgba(255, 255, 0, 0.18), transparent 35%), linear-gradient(135deg, var(--bg1), var(--bg2)); display: flex; align-items: center; justify-content: center; position: relative; } .stars, .effects, .bg-bursts, .rain-layer { position: fixed; inset: 0; pointer-events: none; overflow: hidden; } .star { position: absolute; width: 3px; height: 3px; background: white; border-radius: 50%; opacity: 0.7; animation: twinkle linear infinite; } @keyframes twinkle { 0% { transform: translateY(0) scale(0.6); opacity: 0.2; } 50% { opacity: 1; } 100% { transform: translateY(-20px) scale(1.2); opacity: 0.2; } } .app { width: min(920px, calc(100vw - 32px)); padding: 28px; border-radius: 28px; background: rgba(12, 15, 38, 0.62); backdrop-filter: blur(12px); border: 1px solid var(--panel-border); box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45), inset 0 0 30px rgba(255, 255, 255, 0.06); position: relative; z-index: 2; } .topbar { display: flex; justify-content: space-between; gap: 12px; align-items: center; margin-bottom: 16px; flex-wrap: wrap; } .badge, .score { padding: 10px 16px; border-radius: 999px; background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255,255,255,0.18); box-shadow: var(--glow); font-weight: 700; letter-spacing: 0.06em; } h1 { margin: 8px 0 6px; font-size: clamp(2rem, 4vw, 3.2rem); text-align: center; text-shadow: 0 0 18px rgba(255,255,255,0.35); } .sub { text-align: center; opacity: 0.88; margin-bottom: 26px; font-size: 1rem; } .buttons { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; } .mood-btn { position: relative; overflow: hidden; border: none; border-radius: 22px; padding: 18px 14px; min-height: 120px; cursor: pointer; color: white; font-size: 1.05rem; font-weight: 800; letter-spacing: 0.04em; transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease; box-shadow: 0 10px 24px rgba(0,0,0,0.3); } .mood-btn:hover { transform: translateY(-4px) scale(1.02); filter: brightness(1.08); } .mood-btn:active { transform: scale(0.98); } .mood-btn::before { content: ""; position: absolute; inset: 0; background: linear-gradient(120deg, transparent 30%, rgba(255,255,255,0.32), transparent 70%); transform: translateX(-120%); transition: transform 0.6s ease; } .mood-btn:hover::before { transform: translateX(120%); } .best-btn { background: linear-gradient(135deg, #ffb703, #ff5e00, #ff2e63); } .normal-btn { background: linear-gradient(135deg, #38bdf8, #6366f1, #8b5cf6); } .worst-btn { background: linear-gradient(135deg, #475569, #334155, #0f172a); } .btn-emoji { display: block; font-size: 2rem; margin-bottom: 10px; } .result-panel { margin-top: 22px; padding: 22px; border-radius: 24px; background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.14); min-height: 290px; position: relative; overflow: hidden; } .result-bg-glow { position: absolute; inset: -20%; opacity: 0.35; filter: blur(50px); transition: background 0.5s ease, opacity 0.5s ease; z-index: 0; } .result-content { position: relative; z-index: 1; text-align: center; } min-height: 140px; display: flex; align-items: center; justify-content: center; font-size: clamp(4rem, 10vw, 7rem); margin-top: 10px; text-shadow: 0 0 16px rgba(255,255,255,0.25), 0 0 28px rgba(255,255,255,0.18); } display: inline-block; transform-origin: center; } #message { font-size: clamp(1.3rem, 2.4vw, 2rem); font-weight: 900; margin-top: 12px; letter-spacing: 0.03em; } margin-top: 10px; font-size: 1rem; opacity: 0.9; } .meter-wrap { width: min(460px, 100%); margin: 22px auto 0; text-align: left; } .meter-label { font-size: 0.95rem; margin-bottom: 8px; opacity: 0.9; } .meter { width: 100%; height: 18px; border-radius: 999px; background: rgba(255,255,255,0.1); overflow: hidden; border: 1px solid rgba(255,255,255,0.16); } .meter-bar { height: 100%; width: 0%; border-radius: 999px; transition: width 0.7s cubic-bezier(.2,.8,.2,1), background 0.4s ease; box-shadow: 0 0 18px rgba(255,255,255,0.4); } .floating-text { position: absolute; font-weight: 900; font-size: 1.1rem; opacity: 0; animation: floatUp 1.2s ease forwards; text-shadow: 0 0 12px rgba(255,255,255,0.4); pointer-events: none; white-space: nowrap; } @keyframes floatUp { 0% { transform: translateY(0) scale(0.8); opacity: 0; } 20% { opacity: 1; } 100% { transform: translateY(-70px) scale(1.15); opacity: 0; } } .bounce { animation: bounceEmoji 0.9s cubic-bezier(.2,.8,.2,1); } .gentle { animation: gentleFloat 2.2s ease-in-out infinite; } .shake { animation: shakeSad 0.6s linear 2; } @keyframes bounceEmoji { 0% { transform: scale(0.3) rotate(-20deg); } 30% { transform: scale(1.35) rotate(8deg); } 55% { transform: scale(0.92) rotate(-6deg); } 75% { transform: scale(1.1) rotate(4deg); } 100% { transform: scale(1) rotate(0deg); } } @keyframes gentleFloat { 0% { transform: translateY(0) rotate(0deg); } 25% { transform: translateY(-8px) rotate(-2deg); } 50% { transform: translateY(0) rotate(0deg); } 75% { transform: translateY(8px) rotate(2deg); } 100% { transform: translateY(0) rotate(0deg); } } @keyframes shakeSad { 0% { transform: translateX(0); } 20% { transform: translateX(-8px); } 40% { transform: translateX(8px); } 60% { transform: translateX(-6px); } 80% { transform: translateX(6px); } 100% { transform: translateX(0); } } .confetti, .spark, .rain-drop, .burst-ring { position: absolute; pointer-events: none; } .confetti { width: 12px; height: 22px; opacity: 0.95; animation: confettiFall 2.8s linear forwards; } @keyframes confettiFall { 0% { transform: translateY(-10vh) rotate(0deg); opacity: 1; } 100% { transform: translateY(110vh) translateX(var(--drift, 0px)) rotate(720deg); opacity: 0; } } .spark { font-size: 1.6rem; animation: sparkFly 1s ease-out forwards; opacity: 0; } @keyframes sparkFly { 0% { transform: translate(0, 0) scale(0.4); opacity: 0; } 20% { opacity: 1; } 100% { transform: translate(var(--x), var(--y)) scale(1.3); opacity: 0; } } .burst-ring { width: 30px; height: 30px; border: 4px solid rgba(255,255,255,0.8); border-radius: 50%; animation: burst 0.7s ease-out forwards; } @keyframes burst { 0% { transform: scale(0.2); opacity: 1; } 100% { transform: scale(6); opacity: 0; } } .rain-drop { width: 2px; height: 18px; background: linear-gradient(to bottom, rgba(180,220,255,0), rgba(180,220,255,0.95)); animation: rainFall linear forwards; } @keyframes rainFall { from { transform: translateY(-20px); opacity: 0.8; } to { transform: translateY(110vh); opacity: 0.1; } } .flash-happy { animation: bgFlashHappy 1s ease; } .flash-normal { animation: bgFlashNormal 1s ease; } .flash-worst { animation: bgFlashWorst 1s ease; } @keyframes bgFlashHappy { 0%,100% { filter: brightness(1); } 20% { filter: brightness(1.5) saturate(1.4); } 50% { filter: brightness(1.2) saturate(1.3); } } @keyframes bgFlashNormal { 0%,100% { filter: brightness(1); } 30% { filter: brightness(1.25) hue-rotate(20deg); } } @keyframes bgFlashWorst { 0%,100% { filter: brightness(1); } 30% { filter: brightness(0.75) saturate(0.7); } } .footer-tip { margin-top: 16px; text-align: center; font-size: 0.92rem; opacity: 0.78; } @media (max-width: 720px) { .buttons { grid-template-columns: 1fr; } .mood-btn { min-height: 96px; } .app { padding: 20px; } .result-panel { min-height: 260px; } } </style> </head> <body> <div class="stars" id="stars"></div> <div class="bg-bursts" id="bgBursts"></div> <div class="rain-layer" id="rainLayer"></div> <div class="effects" id="effects"></div> <main class="app" id="app"> <div class="topbar"> <div class="badge">MOOD SELECT</div> <div class="score" id="scoreBoard">テンション: --</div> </div> <h1>今日の気分は?</h1> <div class="sub">ボタンを押すと、ゲームみたいな演出で気分を表示します</div> <section class="buttons"> <button class="mood-btn best-btn" onclick="setMood('best')"> <span class="btn-emoji">😆🎉</span> 最高 </button> <button class="mood-btn normal-btn" onclick="setMood('normal')"> <span class="btn-emoji">🙂✨</span> 普通 </button> <button class="mood-btn worst-btn" onclick="setMood('worst')"> <span class="btn-emoji">😭🌧️</span> 最悪 </button> </section> <section class="result-panel" id="resultPanel"> <div class="result-bg-glow" id="resultGlow"></div> <div class="result-content"> <div id="emojiStage"> <span id="mainEmoji">🎮</span> </div> <div id="message">気分を選んでスタート!</div> <div id="subMessage">今日はどんな一日?</div> <div class="meter-wrap"> <div class="meter-label">気分ゲージ</div> <div class="meter"> <div class="meter-bar" id="meterBar"></div> </div> </div> </div> </section> <div class="footer-tip">最高で祝福演出 / 普通でやさしい演出 / 最悪で雨とダーク演出</div> </main> <script> const mainEmoji = document.getElementById("mainEmoji"); const message = document.getElementById("message"); const subMessage = document.getElementById("subMessage"); const meterBar = document.getElementById("meterBar"); const effects = document.getElementById("effects"); const app = document.getElementById("app"); const body = document.body; const scoreBoard = document.getElementById("scoreBoard"); const rainLayer = document.getElementById("rainLayer"); const bgBursts = document.getElementById("bgBursts"); const resultGlow = document.getElementById("resultGlow"); createStars(); function createStars() { const stars = document.getElementById("stars"); for (let i = 0; i < 60; i++) { const s = document.createElement("div"); s.className = "star"; s.style.left = Math.random() * 100 + "vw"; s.style.top = Math.random() * 100 + "vh"; s.style.animationDuration = (2 + Math.random() * 4) + "s"; s.style.animationDelay = (Math.random() * 3) + "s"; s.style.opacity = 0.2 + Math.random() * 0.8; const size = 2 + Math.random() * 3; s.style.width = size + "px"; s.style.height = size + "px"; stars.appendChild(s); } } function resetAnimations() { mainEmoji.className = ""; body.classList.remove("flash-happy", "flash-normal", "flash-worst"); rainLayer.innerHTML = ""; } function setMood(mood) { resetAnimations(); clearOldEffects(); if (mood === "best") { mainEmoji.textContent = "😆"; mainEmoji.classList.add("bounce"); message.textContent = "SUPER HAPPY !!"; subMessage.textContent = "今日はノリノリ!最強の一日が始まる!"; meterBar.style.width = "100%"; meterBar.style.background = "linear-gradient(90deg, #ffe600, #ff7b00, #ff2e63)"; scoreBoard.textContent = "テンション: MAX"; resultGlow.style.background = "radial-gradient(circle, rgba(255,230,0,0.75), rgba(255,100,0,0.2), transparent 60%)"; body.classList.add("flash-happy"); launchConfetti(80); launchSparks(26, ["✨", "🎉", "⭐", "💥"]); launchBurstRings(5); spawnFloatingText(["GREAT!", "PERFECT!", "HAPPY!", "BONUS!"], "#ffe96b"); } if (mood === "normal") { mainEmoji.textContent = "🙂"; mainEmoji.classList.add("gentle"); message.textContent = "NORMAL MODE"; subMessage.textContent = "今日は落ち着いて、いい感じに過ごせそう。"; meterBar.style.width = "55%"; meterBar.style.background = "linear-gradient(90deg, #60a5fa, #6366f1, #a855f7)"; scoreBoard.textContent = "テンション: MID"; resultGlow.style.background = "radial-gradient(circle, rgba(96,165,250,0.55), rgba(99,102,241,0.18), transparent 60%)"; body.classList.add("flash-normal"); launchSparks(12, ["✨", "💫", "🫧"]); pulseBackground(4, "rgba(120,160,255,0.18)"); spawnFloatingText(["GOOD", "CALM", "OK!"], "#b9c8ff"); } if (mood === "worst") { mainEmoji.textContent = "😭"; mainEmoji.classList.add("shake"); message.textContent = "CRITICAL DAMAGE..."; subMessage.textContent = "今日は無理せず、ゆっくり休もう。"; meterBar.style.width = "15%"; meterBar.style.background = "linear-gradient(90deg, #64748b, #334155, #0f172a)"; scoreBoard.textContent = "テンション: LOW"; resultGlow.style.background = "radial-gradient(circle, rgba(90,110,140,0.35), rgba(20,25,40,0.12), transparent 60%)"; body.classList.add("flash-worst"); startRain(80); launchSparks(8, ["💧", "🌧️", "☔"]); spawnFloatingText(["OOPS...", "SAD...", "REST"], "#cbd5e1"); } } function clearOldEffects() { effects.innerHTML = ""; bgBursts.innerHTML = ""; } function launchConfetti(count) { const colors = ["#ff4d6d", "#ffd60a", "#00f5d4", "#ffffff", "#7b2cff", "#ff8c42"]; for (let i = 0; i < count; i++) { const piece = document.createElement("div"); piece.className = "confetti"; piece.style.left = Math.random() * 100 + "vw"; piece.style.top = (-10 - Math.random() * 20) + "vh"; piece.style.background = colors[Math.floor(Math.random() * colors.length)]; piece.style.borderRadius = Math.random() > 0.5 ? "2px" : "999px"; piece.style.animationDuration = (1.8 + Math.random() * 1.6) + "s"; piece.style.animationDelay = (Math.random() * 0.35) + "s"; piece.style.setProperty("--drift", (Math.random() * 220 - 110) + "px"); effects.appendChild(piece); setTimeout(() => piece.remove(), 3600); } } function launchSparks(count, icons) { for (let i = 0; i < count; i++) { const spark = document.createElement("div"); spark.className = "spark"; spark.textContent = icons[Math.floor(Math.random() * icons.length)]; spark.style.left = "50vw"; spark.style.top = "42vh"; const angle = Math.random() * Math.PI * 2; const distance = 80 + Math.random() * 220; spark.style.setProperty("--x", Math.cos(angle) * distance + "px"); spark.style.setProperty("--y", Math.sin(angle) * distance + "px"); spark.style.animationDuration = (0.8 + Math.random() * 0.7) + "s"; effects.appendChild(spark); setTimeout(() => spark.remove(), 1800); } } function launchBurstRings(count) { for (let i = 0; i < count; i++) { const ring = document.createElement("div"); ring.className = "burst-ring"; ring.style.left = (45 + Math.random() * 10) + "vw"; ring.style.top = (34 + Math.random() * 12) + "vh"; ring.style.animationDelay = (i * 0.08) + "s"; effects.appendChild(ring); setTimeout(() => ring.remove(), 1200); } } function startRain(count) { for (let i = 0; i < count; i++) { const drop = document.createElement("div"); drop.className = "rain-drop"; drop.style.left = Math.random() * 100 + "vw"; drop.style.top = (-20 - Math.random() * 400) + "px"; drop.style.animationDuration = (0.7 + Math.random() * 0.8) + "s"; drop.style.animationDelay = (Math.random() * 0.6) + "s"; rainLayer.appendChild(drop); setTimeout(() => drop.remove(), 2200); } } function pulseBackground(count, color) { for (let i = 0; i < count; i++) { const pulse = document.createElement("div"); pulse.className = "burst-ring"; pulse.style.left = "50vw"; pulse.style.top = "45vh"; pulse.style.borderColor = color; pulse.style.animationDuration = (0.8 + i * 0.2) + "s"; bgBursts.appendChild(pulse); setTimeout(() => pulse.remove(), 1800); } } function spawnFloatingText(words, color) { for (let i = 0; i < 4; i++) { const text = document.createElement("div"); text.className = "floating-text"; text.textContent = words[Math.floor(Math.random() * words.length)]; text.style.color = color; text.style.left = (20 + Math.random() * 60) + "%"; text.style.top = (52 + Math.random() * 18) + "%"; text.style.animationDelay = (i * 0.08) + "s"; effects.appendChild(text); setTimeout(() => text.remove(), 1600); } } </script> </body> </html> |
生成AIを使えばコード作成も簡単
上記のような「コードを書くのは難しそう」と感じる方もいるかもしれません。
しかし、ChatGPTのような生成AIを使えば、コード作成のハードルは大きく下がります。このコードもわずか数分で生成できました。
例えば今回は次のように依頼しました。
HTMLで下記の動作をするコードを生成して。 今日の気分はという問いに対して、選択肢が、最高、普通、最悪とあり、最高を選ぶとハッピーな表現、普通を選ぶと普通の表現、最悪を選ぶと最悪な表現がされる

するとAIがHTMLやJavaScriptのコードを生成してくれます。
今回は続いて次のような依頼をしました。
絵文字を派手にアニメーションさせて

さらに次の依頼をしました。
さらに派手にして、ゲームレベルのUIにして。

以下が生成されたコードを埋め込んだものです。この部分をRiseにも簡単に埋め込めるようになりました。
コードをRiseのCodeブロックに貼り付けるだけで、インタラクティブなコンテンツを作ることができます。
つまり、
Rise × 生成AI
という組み合わせによって、専門的なプログラミング知識がなくても、より高度な学習体験を作れるようになります。
将来はRise単体でAI生成ができる?
現在は別途、生成AIでコードを作り、それをRiseに貼り付ける形になります。
しかし将来的には、Riseの中で直接同様のことができるようになるかもしれません。
こうした指示を出すだけで、Riseが自動的にコードを生成し、Codeブロックとして配置してくれる未来も想像できます。
もしそれが実現すれば、eラーニング制作のハードルはさらに下がるでしょう。
まとめ
Articulate RiseのCodeブロックは、これまでのRiseの可能性を大きく広げる機能です。
HTML・CSS・JavaScriptを活用することで、
インタラクティブな学習
カスタムUI
シミュレーション
ミニゲーム
など、より豊かな学習体験を作ることができます。
さらに生成AIを組み合わせれば、コード作成の難易度も大きく下がります。
これからのeラーニング制作は、このような新しい形に進化していくのかもしれません。
RiseのCodeブロックは、その第一歩となる機能と言えるでしょう。
Articulate 360を試してみたい方は、Articulate 360の30日間の無料トライアルをお試しください。ご登録にクレジットカードは必要ありません!!
株式会社ディーシェは日本におけるArticulate製品の販売代理店です



I particularly liked how you touched on the practical side of it—being able to either write code directly or upload a complete project makes it accessible for both beginners and more advanced users. Features like real-time previews and embedding custom interactions really expand what instructional designers can achieve inside Rise . It’s a great step toward more flexible and engaging e-learning design.What stands out most is how this bridges the gap between traditional block-based content and fully customized experiences, giving creators much more creative control without leaving the platform . It definitely feels like a feature that can transform how courses are built moving forward.This actually reminded me of a similar perspective I came across on a review blog fake…