prettify

baseline

SVG Javascript with events

I need a widget displaying the months of the year. I implemented using SVG and not by Canvas because I needed the capability of SVG to assign events to any element of the picture.
  • The user should be able to select a month by clicking on it
  • The widget should give an event for every month change
  • The user should be able to deselect a month by clicking on it or at the center of the wheel.
It really works! Try it.
Usage (MonthWheel.htm):
<!DOCTYPE html>
<html> 
<head>
    <title>svg</title>
<script type="text/javascript" src="dom.js"></script>
<script type="text/javascript" src="MonthWheel.js"></script>
<script type="text/javascript">
window.onload = function () {
    var oWheel = new MonthWheel($("divSeasons"), 400, 400);
    oWheel.eLang = "en";
    oWheel.MonthChanged = function () {
        if (oWheel.nMonth === -1) return;
        $("divChanges").a$({ 
            t: MonthWheel.Months[oWheel.nMonth][oWheel.eLang]+ " "});
    };
    oWheel.Show();
};
</script>
</head>
<body>
<div id="divSeasons"></div>
<div id="divChanges"></div>
</body>
</html>
The code for dom.js is in an older post. MontWheel.js:
function MonthWheel(oContainer,nWidth,nHeight) {
    var that = this;
    this.oContainer = oContainer;
    this.eLang = "en";
    this.nWidth = 100;
    this.nHeight = 100;
    this.nMonth = -1;
    //events
    this.MonthChanged =null;
    if (typeof nWidth === "number") {
        this.nWidth = nWidth;
        if (typeof nHeight === "number") {
            this.nHeight = nHeight;
        }
    }
    this.SelectMonth = function () {
        var nMonth = parseInt(this.attributes["nMonth"].nodeValue);
        nMonth = (nMonth === that.nMonth) ? -1 : nMonth;
        that.SetMonth(nMonth);

    };
    this.SetMonth = function (nMonth) {
        if (typeof nMonth !== "number") nMonth = -1;
        if (nMonth === that.nMonth) return;
        that.nMonth = nMonth;
        that.Show();
        if (typeof that.MonthChanged === "function") that.MonthChanged();
    }
}
MonthWheel.Months=[
    { en: "Jan", el: "Ιαν", color: "44f", stroke: "008" }
    , { en: "Feb", el: "Φεβ", color: "08f", stroke: "048" }
    , { en: "Mar", el: "Μαρ", color: "0f8", stroke: "084" }
    , { en: "Apr", el: "Απρ", color: "4f4", stroke: "080" }
    , { en: "May", el: "Μαι", color: "8f4", stroke: "480" }
    , { en: "Jun", el: "Ιουν", color: "cf0", stroke: "680" }
    , { en: "Jul", el: "Ιουλ", color: "ff0", stroke: "880" }
    , { en: "Aug", el: "Αυγ", color: "fc0", stroke: "860" }
    , { en: "Sep", el: "Σεπ", color: "f80", stroke: "840" }
    , { en: "Oct", el: "Οκτ", color: "f44", stroke: "800" }
    , { en: "Nov", el: "Νοε", color: "f48", stroke: "804" }
    , { en: "Dec", el: "Δεκ", color: "84f", stroke: "408" }
];
MonthWheel.prototype.Show = function () {
    var oFra = document.createDocumentFragment();
    var nRadius = 1000, nRad = 1000;
    var oSvg = oFra.a$("svg:svg", {
        width: this.nWidth.toString() + "px",
        height: this.nHeight.toString() + "px",
        viewBox: "-" + (nRadius + 100).toString() +
        " -" + (nRadius + 100).toString() +
        " " + (2 * (nRadius + 100)).toString() +
        " " + (2 * (nRadius + 100)).toString()
    });
    var nMonth = 0, oMonth, oPath, oText;
    var nX, nY, nAngle = 0, nAngle2 = Math.PI / 6;
    oSvg.a$("svg:circle", { r: nRadius, style:"fill:#ccc;cursor:pointer;"
        }).onclick = this.SetMonth;
    for (nMonth = 0; nMonth < 12; nMonth++) {
        nRad = (nMonth === this.nMonth) ? nRadius * 1.07 : nRadius;
        oMonth = MonthWheel.Months[nMonth];
        nAngle = nMonth * Math.PI / 6;
        nX = nRad * Math.sin(nAngle);
        nY = -1 * nRad * Math.cos(nAngle);
        nX2 = nRad * Math.sin(nAngle + Math.PI / 6);
        nY2 = -1 * nRad * Math.cos(nAngle + Math.PI / 6);
        oPath = oSvg.a$("svg:path", {
            id: "pat" + oMonth.en,
            nMonth: nMonth,
            style: "fill:#" + oMonth.color + ";stroke:#" + oMonth.stroke +
                ";strokeWidth:20;cursor:pointer;",
            d: "M" +
            nX.toString() + "," + nY.toString() +
            " A" + nRad.toString() + "," + nRad.toString() + " 0 0 1 " +
            nX2.toString() + "," + nY2.toString() +
            " L" + (nX2 / 2).toString() + "," + (nY2 / 2).toString() +
            " A " + (nRad / 2).toString() + "," + (nRad / 2).toString() + " 0 0 0 " +
            (nX / 2).toString() + "," + (nY / 2).toString() + " z"
        });
        oPath.onclick = this.SelectMonth;
        oText = oSvg.a$("svg:text", { x: (nX + nX2) * 3 / 8, y: (nY + nY2) * 3 / 8,
            t: oMonth[this.eLang], nMonth: nMonth, 
            style:"fontSize:100px;textAnchor:middle;cursor:pointer;color:#ccc;" });
        oText.onclick = this.SelectMonth;
    }
    this.oContainer.innerHTML = "";
    this.oContainer.appendChild(oFra);
}

No comments:

Post a Comment