Compare commits
15 Commits
resizeSvg
...
67fc0d4297
Author | SHA1 | Date | |
---|---|---|---|
67fc0d4297 | |||
6716a4cd40 | |||
4e4570ed03 | |||
12d53370fb | |||
11b9635e50 | |||
d769797136 | |||
4804497b3c | |||
80529e5882 | |||
f6abc396b6 | |||
094d756a07 | |||
fca0d3a5fa | |||
5efb1ad322 | |||
2e85a7c2b3 | |||
4658ec5a9d | |||
364a64f320 |
104
index.html
104
index.html
@@ -57,6 +57,8 @@
|
||||
.translationText, .romanizationText {
|
||||
visibility: hidden;
|
||||
font-family: "Noto Sans";
|
||||
/* font-size:1.2em; */
|
||||
/* font-size: max(0.8vmax, 16px);*/
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
@@ -67,13 +69,11 @@
|
||||
.languageText {
|
||||
pointer-events: none;
|
||||
font-weight: bold;
|
||||
font-size: 1em;
|
||||
/* font-size: 1em;*/
|
||||
font-size: max(0.7vmax, 14px);
|
||||
font-family: sans-serif;
|
||||
visibility: hidden;
|
||||
}
|
||||
.language:hover ~ .languageText {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.district {
|
||||
stroke: white;
|
||||
@@ -113,10 +113,83 @@
|
||||
transition: fill-opacity 0.3s;
|
||||
}
|
||||
|
||||
section#textStuff {
|
||||
min-width: 30em;
|
||||
/* flex: 0 1 0; */
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
section#textStuff ul {
|
||||
font-size: 1.2em;
|
||||
line-height: 1.5rem;
|
||||
max-width: 35em;
|
||||
}
|
||||
|
||||
section#textStuff li {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
#query {
|
||||
font-size: 1em;
|
||||
padding: 6px 8px;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
#submitButton {
|
||||
appearance: none;
|
||||
background-color: #2ea44f;
|
||||
border: 1px solid rgba(27, 31, 35, .15);
|
||||
border-radius: 6px;
|
||||
box-shadow: rgba(27, 31, 35, .1) 0 1px 0;
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 1em;
|
||||
font-weight: 600;
|
||||
line-height: 1.2em;
|
||||
padding: 6px 16px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
touch-action: manipulation;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#submitButton:focus:not(:focus-visible):not(.focus-visible) {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#submitButton:hover {
|
||||
background-color: #2c974b;
|
||||
}
|
||||
|
||||
#submitButton:focus {
|
||||
box-shadow: rgba(46, 164, 79, .4) 0 0 0 3px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#submitButton:disabled {
|
||||
background-color: #94d3a2;
|
||||
border-color: rgba(27, 31, 35, .1);
|
||||
color: rgba(255, 255, 255, .8);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#submitButton:active {
|
||||
background-color: #298e46;
|
||||
box-shadow: rgba(20, 70, 32, .2) 0 1px 0 inset;
|
||||
}
|
||||
|
||||
/* Position map load spinner in the middle of the SVG */
|
||||
#svgContainer {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
max-width: 100%;
|
||||
}
|
||||
@@ -178,7 +251,7 @@
|
||||
#fetchingText {
|
||||
visibility: hidden;
|
||||
}
|
||||
@media only screen and (max-width: 768px) {
|
||||
@media only screen and (max-width: 1366px) {
|
||||
main {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
@@ -187,7 +260,7 @@
|
||||
stroke-width: 0.1;
|
||||
}
|
||||
.translationText, .romanizationText {
|
||||
font-size: 0.7em;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.languageText {
|
||||
font-size: 0.6em;
|
||||
@@ -195,6 +268,14 @@
|
||||
|
||||
}
|
||||
|
||||
/* @media only screen and (max-width: 768px) {
|
||||
.translationText, .romanizationText {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.languageText {
|
||||
font-size: 0.6em;
|
||||
}
|
||||
} */
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -204,13 +285,21 @@
|
||||
<form hx-get="/submit" hx-swap=none hx-indicator="#loading-screen" hx-on::before-request="hideTranslationsAndShowText(event.detail.xhr.response)" hx-on::after-request="updateTranslations(event.detail.xhr.response)" class="translateForm" method="get">
|
||||
<label for="query">Enter text to translate:</label>
|
||||
<input type="text" name="query" id="query" required/>
|
||||
<input type="submit" value="Translate"/>
|
||||
<input type="submit" id="submitButton" value="Translate"/>
|
||||
</form>
|
||||
<progress id="loading-screen" class="loading-indicator"></progress>
|
||||
<h3 id="fetchingText">Fetching translations...</h3>
|
||||
<noscript>
|
||||
<h2>This website requires javascript to work.</h2>
|
||||
</noscript>
|
||||
<ul>
|
||||
<li>Enter text in English. Translations are displayed on the map, along with romanizations (translation converted to Latin script).</li>
|
||||
<li>Hover over a language region (denoted by color) to see the language spoken in the region. Language boundaries were drawn using census data; they may be inaccurate.</li>
|
||||
<li>Translations are retrieved from Google Translate - they may be innacurate.</li>
|
||||
<li>Romanizations are made with the <kbd>ai4bharat-transliteration</kbd> AI model, developed by <a href="https://ai4bharat.iitm.ac.in/">Ai4Bharat</a>.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="svgContainer">
|
||||
@@ -220,6 +309,7 @@
|
||||
|
||||
<script type="text/javascript" src="index.js"></script>
|
||||
<script type="text/javascript" src="updateTranslations.js"></script>
|
||||
<script type="text/javascript" src="svgHoverListener.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
|
130
index.js
130
index.js
@@ -1,28 +1,28 @@
|
||||
const defaultColor = "#555555"
|
||||
|
||||
const languages = {
|
||||
tamil: {name: "Tamil", color: "#75d795", code: "ta", districts: []},
|
||||
malayalam: {name: "Malayalam", color: "#ff7c7c", code: "ml", districts: []},
|
||||
kannada: {name: "Kannada", color: "#ffe77c", code: "kn", districts: []},
|
||||
telugu: {name: "Telugu", color: "#7c9dff", code: "te", districts: []},
|
||||
marathi: {name: "Marathi", color: "#e0ff7c", code: "mr", districts: []},
|
||||
konkani: {name: "Konkani", color: "#9b7cff", code: "gom", districts: []},
|
||||
hindi: {name: "Hindi", color: "#d17cff", code: "hi", districts: []},
|
||||
gujarati: {name: "Gujarati", color: "#7cffee", code: "gu", districts: []},
|
||||
oriya: {name: "Oriya", color: "#9bcc9f", code: "or", districts: []},
|
||||
bengali: {name: "Bengali", color: "#bf9a77", code: "bn", districts: []},
|
||||
punjabi: {name: "Punjabi", color: "#e84a35", code: "pa", districts: []},
|
||||
mizo: {name: "Mizo", color: "#a6a4de", code: "lus", districts: []},
|
||||
assamese: {name: "Assamese", color: "#c9535b", code: "as", districts: []},
|
||||
bhojpuri: {name: "Bhojpuri", color: "#b3b876", code: "bho", districts: []},
|
||||
manipuri: {name: "Manipuri", color: "#c9afad", code: "mni-Mtei", districts: []},
|
||||
dogri: {name: "Dogri", color: "#9595e6", code: "doi", districts: []},
|
||||
nepali: {name: "Nepali", color: "#71998e", code: "ne", districts: []},
|
||||
urdu: {name: "Urdu", color: "#3fa179", code: "ur", districts: []},
|
||||
tulu: {name: "Tulu", color: "#dedc52", code: "tcy", districts: []},
|
||||
maithali: {name: "Maithali", color: "#4472a6", code: "mai", districts: []},
|
||||
sindhi: {name: "Sindhi", color: "#e89931", code: "sd", districts: []},
|
||||
awadhi: {name: "Awadhi", color: "#847fb5", code: "awa", districts: []},
|
||||
tamil: {name: "Tamil", color: "#75d795", code: "ta", text_align: "start", districts: []},
|
||||
malayalam: {name: "Malayalam", color: "#ff7c7c", code: "ml", text_align: "end", districts: []},
|
||||
kannada: {name: "Kannada", color: "#ffe77c", code: "kn", text_align: "middle", districts: []},
|
||||
telugu: {name: "Telugu", color: "#7c9dff", code: "te", text_align: "start", districts: []},
|
||||
marathi: {name: "Marathi", color: "#e0ff7c", code: "mr", text_align: "middle", districts: []},
|
||||
konkani: {name: "Konkani", color: "#9b7cff", code: "gom", text_align: "end", districts: []},
|
||||
hindi: {name: "Hindi", color: "#d17cff", code: "hi", text_align: "middle", districts: []},
|
||||
gujarati: {name: "Gujarati", color: "#7cffee", code: "gu", text_align: "middle", districts: []},
|
||||
oriya: {name: "Oriya", color: "#9bcc9f", code: "or", text_align: "middle", districts: []},
|
||||
bengali: {name: "Bengali", color: "#bf9a77", code: "bn", text_align: "middle", districts: []},
|
||||
punjabi: {name: "Punjabi", color: "#e84a35", code: "pa", text_align: "middle", districts: []},
|
||||
mizo: {name: "Mizo", color: "#a6a4de", code: "lus", text_align: "middle", districts: []},
|
||||
assamese: {name: "Assamese", color: "#c9535b", code: "as", text_align: "middle", districts: []},
|
||||
bhojpuri: {name: "Bhojpuri", color: "#b3b876", code: "bho", text_align: "end", districts: []},
|
||||
manipuri: {name: "Manipuri", color: "#c9afad", code: "mni-Mtei", text_align: "middle", districts: []},
|
||||
dogri: {name: "Dogri", color: "#9595e6", code: "doi", text_align: "middle", districts: []},
|
||||
nepali: {name: "Nepali", color: "#71998e", code: "ne", text_align: "middle", districts: []},
|
||||
urdu: {name: "Urdu", color: "#3fa179", code: "ur", text_align: "middle", districts: []},
|
||||
tulu: {name: "Tulu", color: "#dedc52", code: "tcy", text_align: "end", districts: []},
|
||||
maithali: {name: "Maithali", color: "#4472a6", code: "mai", text_align: "middle", districts: []},
|
||||
sindhi: {name: "Sindhi", color: "#e89931", code: "sd", text_align: "middle", districts: []},
|
||||
awadhi: {name: "Awadhi", color: "#847fb5", code: "awa", text_align: "middle", districts: []},
|
||||
};
|
||||
|
||||
// Credit: https://www.artcraftblend.com/blogs/colors/shades-of-pastel
|
||||
@@ -213,9 +213,14 @@ function stateOrDistrictOrLanguage(d) {
|
||||
|
||||
// const mapWidth = document.getElementById("indiaMap").getAttribute("width")
|
||||
// const mapHeight = document.getElementById("indiaMap").getAttribute("height")
|
||||
const mapWidth = /*window.innerWidth - */document.querySelector("#svgContainer").offsetWidth * 0.85;
|
||||
let mapWidth = /*window.innerWidth - */document.querySelector("#svgContainer").offsetWidth * 0.85;
|
||||
// const mapHeight = document.querySelector("#svgContainer").offsetHeight;
|
||||
const mapHeight = (window.innerHeight - document.querySelector("#svgContainer").getBoundingClientRect().top);
|
||||
let mapHeight = (window.innerHeight - document.querySelector("#svgContainer").getBoundingClientRect().top);
|
||||
|
||||
if (window.innerWidth <= 768) {
|
||||
mapWidth *= 1.5;
|
||||
mapHeight *= 1.5;
|
||||
}
|
||||
|
||||
const svg = d3.select("#svgContainer")
|
||||
.append('svg')
|
||||
@@ -227,7 +232,12 @@ const svg = d3.select("#svgContainer")
|
||||
// .call(responsivefy);
|
||||
|
||||
function drawMap(world) {
|
||||
const projection = d3.geoMercator().fitSize([mapWidth, mapHeight], world)
|
||||
let projection = null;
|
||||
if (window.innerWidth > 1366) {
|
||||
projection = d3.geoMercator().fitSize([mapWidth, mapHeight], world)
|
||||
} else {
|
||||
projection = d3.geoMercator().fitWidth(mapWidth, world)
|
||||
}
|
||||
const path = d3.geoPath().projection(projection);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
@@ -235,9 +245,9 @@ function drawMap(world) {
|
||||
const bbox = newSvg.node().getBBox();
|
||||
const originalWidth = +newSvg.attr("width");
|
||||
newSvg
|
||||
// .attr("viewBox", `${bbox.x} ${bbox.y} ${bbox.width} ${bbox.height}`)
|
||||
.attr("viewBox", `0 ${bbox.y} ${originalWidth} ${bbox.height}`)
|
||||
// .attr("width", mapHeight.toString())
|
||||
.attr("viewBox", `${bbox.x} ${bbox.y} ${bbox.width} ${bbox.height}`)
|
||||
// .attr("viewBox", `0 ${bbox.y} ${originalWidth} ${bbox.height}`)
|
||||
.attr("width", bbox.width)
|
||||
.attr("height", bbox.height)
|
||||
// .style("display", "block")
|
||||
// .style("max-height", "100%"); // optional: keep it scalable in a flexbox
|
||||
@@ -252,6 +262,11 @@ function drawMap(world) {
|
||||
states.append("path")
|
||||
.attr("d", path)
|
||||
.attr("class", d => stateOrDistrictOrLanguage(d))
|
||||
.attr("id", function(d) {
|
||||
if (stateOrDistrictOrLanguage(d) === "language") {
|
||||
return languages[d.properties.lang_name.toLowerCase()].code + "langMap";
|
||||
}
|
||||
})
|
||||
.attr("fill", function(d) {
|
||||
if (stateOrDistrictOrLanguage(d) === "language") {
|
||||
return languages[d.properties.lang_name.toLowerCase()].color;
|
||||
@@ -272,7 +287,8 @@ function drawMap(world) {
|
||||
.append("title") // Tooltip
|
||||
.text(d => d.properties.district);
|
||||
|
||||
states.append("text")
|
||||
const textItems = svg.selectAll("g.textItem").data(world.features).enter().append("g");
|
||||
textItems.append("text")
|
||||
.attr("x", function(d) {
|
||||
if (stateOrDistrictOrLanguage(d) == "language") {
|
||||
rtv = projection(d3.geoCentroid(d))[0];
|
||||
@@ -280,7 +296,10 @@ function drawMap(world) {
|
||||
rtv -= 20;
|
||||
}
|
||||
if (d.properties.lang_name == "Tamil") {
|
||||
rtv += 20;
|
||||
rtv -= 10;
|
||||
}
|
||||
if (d.properties.lang_name == "Kannada" && window.innerWidth <= 768) {
|
||||
rtv += 15;
|
||||
}
|
||||
if (d.properties.lang_name == "Maithali") {
|
||||
rtv += 10;
|
||||
@@ -298,10 +317,15 @@ function drawMap(world) {
|
||||
if (stateOrDistrictOrLanguage(d) == "language") {
|
||||
rtv = projection(d3.geoCentroid(d))[1]
|
||||
if (d.properties.lang_name == "Kannada") {
|
||||
rtv += 15;
|
||||
if (window.innerWidth > 768) {
|
||||
rtv += 10;
|
||||
}
|
||||
}
|
||||
if (d.properties.lang_name == "Tamil") {
|
||||
rtv -= 20;
|
||||
rtv -= 10;
|
||||
}
|
||||
if (d.properties.lang_name == "Malayalam") {
|
||||
rtv += 10;
|
||||
}
|
||||
if (d.properties.lang_name == "Gujarati") {
|
||||
rtv -= 10;
|
||||
@@ -315,12 +339,15 @@ function drawMap(world) {
|
||||
if (d.properties.lang_name == "Bengali") {
|
||||
rtv += 25;
|
||||
}
|
||||
if (d.properties.lang_name == "Hindi") {
|
||||
if (window.innerWidth > 768) {
|
||||
rtv += 3 * parseFloat(getComputedStyle(document.documentElement).fontSize); // rem
|
||||
}
|
||||
}
|
||||
|
||||
return rtv
|
||||
}
|
||||
})
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("fill", "black")
|
||||
.attr("class", "translationText")
|
||||
.attr("id", function(d) {
|
||||
if (stateOrDistrictOrLanguage(d) == "language") {
|
||||
@@ -335,18 +362,18 @@ function drawMap(world) {
|
||||
} else {
|
||||
d3.select(this).remove() // Only add this attribute if the element is a language
|
||||
}
|
||||
});
|
||||
})
|
||||
.attr("text-anchor", d => typeof d.properties.lang_name != "undefined" && languages[d.properties.lang_name.toLowerCase()].text_align)
|
||||
.attr("fill", "black")
|
||||
|
||||
// Romanization
|
||||
states.append("text")
|
||||
textItems.append("text")
|
||||
.attr("x", d => stateOrDistrictOrLanguage(d) == "language" ?
|
||||
document.getElementById(d.properties.lang_code + "Text").getAttribute("x") :
|
||||
projection(d3.geoCentroid(d))[0])
|
||||
.attr("y", d => stateOrDistrictOrLanguage(d) == "language" ?
|
||||
parseFloat(document.getElementById(d.properties.lang_code + "Text").getAttribute("y")) + parseFloat(getComputedStyle(document.getElementsByClassName('translationText')[0]).getPropertyValue('font-size')) :
|
||||
projection(d3.geoCentroid(d))[1])
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("fill", "black")
|
||||
.attr("class", "romanizationText")
|
||||
.attr("id", function(d) {
|
||||
if (stateOrDistrictOrLanguage(d) == "language") {
|
||||
@@ -359,18 +386,18 @@ function drawMap(world) {
|
||||
if (!stateOrDistrictOrLanguage(d) == "language") {
|
||||
d3.select(this).remove() // Only add this attribute if the element is a language
|
||||
}
|
||||
});
|
||||
})
|
||||
.attr("text-anchor", d => typeof d.properties.lang_name != "undefined" && languages[d.properties.lang_name.toLowerCase()].text_align)
|
||||
.attr("fill", "black")
|
||||
|
||||
// Language
|
||||
states.append("text")
|
||||
textItems.append("text")
|
||||
.attr("x", d => stateOrDistrictOrLanguage(d) == "language" ?
|
||||
document.getElementById(d.properties.lang_code + "Text").getAttribute("x") :
|
||||
projection(d3.geoCentroid(d))[0])
|
||||
.attr("y", d => stateOrDistrictOrLanguage(d) == "language" ?
|
||||
parseFloat(document.getElementById(d.properties.lang_code + "Text").getAttribute("y")) - parseFloat(getComputedStyle(document.getElementsByClassName('translationText')[0]).getPropertyValue('font-size')) :
|
||||
projection(d3.geoCentroid(d))[1])
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("fill", "black")
|
||||
.attr("class", "languageText")
|
||||
.attr("id", function(d) {
|
||||
if (stateOrDistrictOrLanguage(d) == "language") {
|
||||
@@ -391,11 +418,30 @@ function drawMap(world) {
|
||||
d3.select(this).remove() // Only add this attribute if the element is a language
|
||||
}
|
||||
})
|
||||
.attr("text-anchor", d => typeof d.properties.lang_name != "undefined" && languages[d.properties.lang_name.toLowerCase()].text_align)
|
||||
.attr("fill", "black")
|
||||
|
||||
let allLangs = []
|
||||
|
||||
const coordinates = [77.69916967457782,23.389970772934166];
|
||||
const [xCoord, yCoord] = projection(coordinates);
|
||||
|
||||
// Add a listener to toggle the language display when a language is hovered on the map
|
||||
document.querySelectorAll(".language").
|
||||
forEach(function(element) {
|
||||
element.addEventListener("mouseover", toggleLanguageDisplay);
|
||||
element.addEventListener("mouseout", toggleLanguageDisplay);
|
||||
});
|
||||
|
||||
// Remove all 'g' elements that have no children (they don't have a language, translation, or romanization). This must mean they accidentally got created when I created the 'textItems' variable
|
||||
document.querySelectorAll("g").
|
||||
forEach(function(element) {
|
||||
if (element.childElementCount == 0) {
|
||||
element.remove()
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// svg.append("text")
|
||||
// .attr("x", xCoord)
|
||||
// .attr("y", yCoord)
|
||||
|
8
svgHoverListener.js
Normal file
8
svgHoverListener.js
Normal file
@@ -0,0 +1,8 @@
|
||||
function toggleLanguageDisplay(event) {
|
||||
if (event.type == "mouseover") {
|
||||
document.getElementById(this.id.replace(/langMap$/, '') + "Language").style.visibility = "visible";
|
||||
}
|
||||
if (event.type == "mouseout") {
|
||||
document.getElementById(this.id.replace(/langMap$/, '') + "Language").style.visibility = "hidden";
|
||||
}
|
||||
}
|
BIN
translations.db
BIN
translations.db
Binary file not shown.
Reference in New Issue
Block a user