Published
Edited
Oct 15, 2021
Insert cell
Insert cell
Insert cell

svg_words = {
const svg = d3.create('svg').attr("width", svg_w).attr("height", svg_h).attr('viewBox',`0 0 ${svg_w} ${svg_h}`)

let space = rowSize
// let space = wordSizes[word.word].height // should I destructure this, and height seems to be a constant

svg.append('rect')
.attr('id','wordRect')
.attr('x',space/2) // .attr('y',space-(space*0.1)) // y position is off in firefox
.attr('y',row[1]) // y position is off in firefox

.attr('width',wordSize[word.word]+space)
.attr('height',space-(space/8)) // maybe I should use rowSize
.attr('rx',15)
.attr('fill','#85CB33')
.attr('stroke-width',1)
.attr('stroke','#041B15')
.attr('cursor','pointer')

.on("click", () => {
let r = teRegions[word.word]
console.log(r)
teReo.start('0.001',r.start, r.length)
return Tone.context.resume()

})

svg.append('text')
.attr('pointer-events','none')
.style('font-family','sans-serif')
.style('font-size', '42px')
.style('alignment-baseline','hanging')
.attr('x',space)
.attr('y',row[1])
.attr('id', `word`)
.text(reo[word.word].Māori+' 🔊');
//-----------------------------------------------------------------------
// guesses
svg.append('rect')
.attr('id','choice0')
.attr('x',space/2) // .attr('y',space-(space*0.1)) // y position is off in firefox
.attr('y',row[2]) // y position is off in firefox

.attr('width',space)
.attr('height',rowSize)
.attr('rx',15)
.attr('fill','#92AD94')
.attr('stroke-width',3)
.attr('stroke','#061A40')

.attr('cursor','pointer')

.on("click", () => {

if (word.word === word.otherWords[0]) {
d3.select('#choice0').attr('fill','red')
} else {
d3.select('#choice0').attr('fill','blue')
}
})

svg.append('text')
.attr('pointer-events','none')
.style('font-family','sans-serif')
.style('font-size', '42px')
.style('alignment-baseline','hanging')
.attr('x',space*2)
.attr('y',row[2])
.attr('id', `word`)
.text(reo[word.otherWords[0]].meaning);
// -----------

svg.append('rect')
.attr('id','choice1')
.attr('x',space/2) // .attr('y',space-(space*0.1)) // y position is off in firefox
.attr('y',row[3]) // y position is off in firefox

.attr('width',space)
.attr('height',rowSize )
.attr('rx',15)
.attr('fill','#92AD94')
.attr('stroke-width',3)
.attr('stroke','#061A40')

.attr('cursor','pointer')

.on("click", () => {
if (word.word === word.otherWords[1]) {
d3.select('#choice1').attr('fill','red')
} else {
d3.select('#choice1').attr('fill','blue')
}
})

svg.append('text')
.attr('pointer-events','none')
.style('font-family','sans-serif')
.style('font-size', '42px')
.style('alignment-baseline','hanging')
.attr('x',space*2)
.attr('y',row[3])
.attr('id', `word`)
.text(reo[word.otherWords[1]].meaning);
// -----------
svg.append('rect')
.attr('id','choice2')
.attr('x',space/2) // .attr('y',space-(space*0.1)) // y position is off in firefox
.attr('y',row[4]) // y position is off in firefox

.attr('width',space)
.attr('height',rowSize )
.attr('rx',15)
.attr('fill','#92AD94')
.attr('stroke-width',3)
.attr('stroke','#061A40')

.attr('cursor','pointer')

.on("click", () => {
if (word.word === word.otherWords[2]) {
d3.select('#choice2').attr('fill','red')
} else {
d3.select('#choice2').attr('fill','blue')
}
})

svg.append('text')
.attr('pointer-events','none')
.style('font-family','sans-serif')
.style('font-size', '42px')
.style('alignment-baseline','hanging')
.attr('x',space*2)
.attr('y',row[4])
.attr('id', `word`)
.text(reo[word.otherWords[2]].meaning);
// -----------
svg.append('rect')
.attr('id','choice3')
.attr('x',space/2) // .attr('y',space-(space*0.1)) // y position is off in firefox
.attr('y',row[5]) // y position is off in firefox

.attr('width',space)
.attr('height',rowSize )
.attr('rx',15)
.attr('fill','#92AD94')
.attr('stroke-width',3)
.attr('stroke','#061A40')

.attr('cursor','pointer')

.on("click", () => {
if (word.word === word.otherWords[3]) {
d3.select('#choice3').attr('fill','red')
} else {
d3.select('#choice3').attr('fill','blue')
}
})

svg.append('text')
.attr('pointer-events','none')
.style('font-family','sans-serif')
.style('font-size', '42px')
.style('alignment-baseline','hanging')
.attr('x',space*2)
.attr('y',row[5])
.attr('id', `word`)
.text(reo[word.otherWords[3]].meaning);
// -----------
svg.append('rect')
.attr('id','choice4')
.attr('x',space/2) // .attr('y',space-(space*0.1)) // y position is off in firefox
.attr('y',row[6]) // y position is off in firefox

.attr('width',space)
.attr('height',rowSize )
.attr('rx',15)
.attr('fill','#92AD94')
.attr('stroke-width',3)
.attr('stroke','#061A40')

.attr('cursor','pointer')

.on("click", () => {
if (word.word === word.otherWords[4]) {
d3.select('#choice4').attr('fill','red')
} else {
d3.select('#choice4').attr('fill','blue')
}
})

svg.append('text')
.attr('pointer-events','none')
.style('font-family','sans-serif')
.style('font-size', '42px')
.style('alignment-baseline','hanging')
.attr('x',space*2)
.attr('y',row[6])
.attr('id', `word`)
.text(reo[word.otherWords[4]].meaning);

// -------------------------------------------------
// next button
svg.append('rect')
.attr('id','nextRect')
.attr('x',space/2)
.attr('y',row[row.length-1])
.attr('width',nextWord.width+space)
.attr('height',space-(space/4))
.attr('rx',15)
.attr('fill','#EF946C')
.attr('cursor','pointer')
.attr('stroke-width',3)
.attr('stroke','#A01A40')

.on("click", () => {

mutable word = pickWords() // This causes this svg_words cell to redraw.

// d3.select('#wordRect')
// .attr('x',space/2)
// .attr('y',space-(space*0.1)) // y position is off in firefox
// .attr('width',wordSizes[word.word].width+space)
// .attr('height',space)

// d3.select('#word')
// .attr('x',svg_w*0.04)
// .attr('y',svg_h*0.1)
// .text(reo[word.word].Māori);
})


svg.append('text')
.attr('pointer-events','none')
.style('font-family','sans-serif')
.style('font-size', '42px')
.style('alignment-baseline','hanging')

.attr('x',svg_w*0.04)
.attr('y',row[row.length-1])

.attr('id', `next`)
.text('Next Word');

return svg.node()
}
Insert cell
I need to wait for the mp3 to be loaded before running other cells.
<pre>
Tone.loaded().then(() => {
teReo.start();
});
</pre>


Insert cell
teReo = new Tone.Player(await FileAttachment("words.mp3").url()).toDestination();
Insert cell
Insert cell
reo[sample] // display text realated to current sample
Insert cell
//teReo.start('0', teRegions[sample].start,teRegions[sample].length) // only works once the mp3 file os loaded
Insert cell
welcome = {
Tone.loaded().then(() => {
// teReo.start('0.001', teRegions[85].start,teRegions[85].length) // Starts with saying Kia ora when the mp3 is loaded.
return Tone.context.resume()
});
}
Insert cell
Tone = require('tone')
Insert cell
toneform = html`
<h3>Play all the words in the Mp3</h3>
<div id="wavDiv"></div><br>
<button id='tplayb'>▶️Play</button> <button id='tpauseb'>⏸Pause</button> <button id='tstopb'>⏹Stop</button>
<br><br>`
Insert cell
tcontrolButtons = {
d3.select('#tplayb').on('click',() => teReo.start())
d3.select('#tpauseb').on('click',() => teReo.pause())
d3.select('#tstopb').on('click',() => teReo.stop("0")) // stops the source 0 seconds from now)
}
Insert cell
Insert cell
Insert cell
audioURL = await FileAttachment("words.mp3").url()
Insert cell
FileAttachment("mania.mp3")
Insert cell
Insert cell
teRegions = FileAttachment('nr.json').json()

Insert cell
reo = FileAttachment("100 Māori words@4.tsv").tsv()
Insert cell
viewof table = Inputs.table(reo, {})
Insert cell
Insert cell
svg_w = width
Insert cell
svg_h = Math.ceil(width/2)
Insert cell
Insert cell
row = {
let r = [];
let s = (rowSize*1.5) // font height in pixels + padding
for (let y = 0; y < ~~(svg_h / s); ++y) {
r.push(~~(y*s))
}
return r
}
Insert cell
rowSize = (textSize('M').height)
Insert cell
Insert cell
wordSize = {
svg_w // run if screen size changes
let ws = []
for (let i = 0; i < reo.length; ++i) {
ws.push(textSize(reo[i].Māori).width)
}
return ws
}
Insert cell
// returns a random word and and array for 5 random words including the test word
mutable word = pickWords()
Insert cell
Insert cell
function pickWords()
{

let w = randomWord() // our random word
let otherWords = []
otherWords.push(w)
for (let i = 0; i < 4; ++i) {
otherWords.push(pick(otherWords))
}

d3.shuffle(otherWords)
return {word:w, otherWords}
}
Insert cell
function pick(numbers){
let p = randomWord()
return (numbers.includes(p))? pick(numbers) : p
}
Insert cell
nextWord = textSize('Next Word') // next word svg button size
Insert cell
randomWord = d3.randomInt(0, reo.length)
Insert cell
Insert cell
function textSize(text) {
let testSize = d3.select('body').append('svg');
testSize.append('text')
.style('font-family','sans-serif') // I should pass these into the function
.style('font-size', '42px')
.text(text);

let sel = testSize.selectAll('text').node()
let width = sel.getComputedTextLength()
let height = sel.getExtentOfChar(0).height
testSize.remove()
return {width, height}
}
// based on: https://gist.github.com/huytd/327e453c95ca3edadb32d0c867e2561b
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more